package com.chinaweal.aiccs.aiccs.business.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinaweal.aiccs.aiccs.abnormal.entity.EBaseinfo;
import com.chinaweal.aiccs.aiccs.business.service.SliceAutoClaimService;
import com.chinaweal.aiccs.aiccs.market.entity.AreaSlice;
import com.chinaweal.aiccs.aiccs.market.entity.dto.EBaseInfoAssignDto;
import com.chinaweal.aiccs.aiccs.market.service.AreaSliceService;
import com.chinaweal.aiccs.aiccs.market.service.BizOwnerAssignService;
import com.chinaweal.aiccs.common.constant.Constant;
import com.chinaweal.aiccs.common.util.AnalysisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 片区自动认领服务实现类（弃用）
 * @author <a href="https://blog.lroyia.top">lroyia</a>
 * @since 2021/5/21 11:25
 **/
@Slf4j
@Service
@Deprecated // 弃用
public class SliceAutoClaimServiceImpl implements SliceAutoClaimService {

    private static final int MAX_RUNNING_SIZE = 10;

    /**队列，用于削峰**/
    private final Queue<String> queue = new LinkedBlockingQueue<>();

    /**中断信号存储map**/
    private final Map<String, Boolean> interruptSignalMap = new ConcurrentHashMap<>(MAX_RUNNING_SIZE);

    /**主执行线程池**/
    private final ExecutorService executorService = Executors.newFixedThreadPool(MAX_RUNNING_SIZE);

    /**是否运行中的标记，用于懒创建**/
    private volatile boolean isRunning = false;

    /**认领分页大小**/
    private final static int CLAIM_PAGE_SIZE = 500;

    /**认领分页对象**/
    private final static IPage<EBaseinfo> PAGE = new Page<>(1, CLAIM_PAGE_SIZE);

    @Autowired
    private AreaSliceService areaSliceService;
    @Autowired
    private BizOwnerAssignService bizOwnerAssignService;

    @PreDestroy
    public void destroyed() {
        executorService.shutdown();
    }

    /**
     * 认领
     * @param sliceId 片区id
     * @author lroyia
     * @since  2021年5月21日 15:13:33
     */
    private void claim(String sliceId){
        AreaSlice area = areaSliceService.getById(sliceId);
        // 校验片区是否存在及其状态
        if(area == null){
            log.error("不存在的片区id：{}", sliceId);
            return;
        }
        if(Constant.FALSE_0_STR.equals(area.getState())){
            log.warn("片区：{}已停用", sliceId);
            return;
        }
        String address = area.getSliceAddr();

        // 辖区
        String region = AnalysisUtils.getRegionGZ(address);
        if(region == null){
            log.warn("片区地址找不到辖区信息，片区：{}", sliceId);
            return;
        }

        // 地址
        String street = AnalysisUtils.getStreetNameByAddress(address);

        String beginPripid = "";
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("streetLong", region + street);

        // 通过比较pripid大小进行循环分页
        while(true){
            paramMap.put("beginPripid", beginPripid);
            IPage<EBaseInfoAssignDto> eachPage = bizOwnerAssignService.ownerAssignPage(PAGE, paramMap);
            if(eachPage.getRecords().size() == 0){
                break;
            }
            List<EBaseInfoAssignDto> records = eachPage.getRecords();
            for (EBaseInfoAssignDto each : records) {
                // 认领实现 TODO: 这里以后要更细化认领规则
                bizOwnerAssignService.areaClaim(sliceId, each.getPripid(), "system");
            }

            // 分页大小比原本当前的小
            if(eachPage.getSize() < CLAIM_PAGE_SIZE){
                break;
            }

            // 更新pripid索引
            beginPripid = records.get(records.size() - 1).getPripid();

        }
    }

    /**
     * 主线程运行方法
     * @author lroyia
     * @since  2021年5月21日 14:42:19
     */
    private synchronized void run(){
        // 主线程
        Thread main = new Thread(() -> {
            /*
             * 主循环
             * 1、执行
             */
            while(true){
                if(interruptSignalMap.size() != MAX_RUNNING_SIZE && !queue.isEmpty()){
                    final String head = queue.poll();
                    executorService.execute(() -> {
                        claim(head);
                        // 结束后唤醒主线程，使其执行队列中的下一个片区认领任务
                        interruptSignalMap.remove(head);
                        synchronized (this){
                            this.notify();
                        }
                    });
                }
                synchronized (this){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        // 程序收到程序中断信号，进行中断
                        break;
                    }
                }
                if(queue.isEmpty()){
                    this.isRunning = false;
                    break;
                }
            }
        });
        main.setName("SliceAutoClaimService@"+this.hashCode() + "MainThread");
        main.start();
    }

    @Override
    public synchronized int runSlice(String sliceId) {
//        if(!isRunning){
//            run();
//            isRunning = true;
//        }
//        // 队列去重
//        if(queue.contains(sliceId) || interruptSignalMap.containsKey(sliceId)){
//            return 1;
//        }
//        queue.add(sliceId);
//        this.notify();
        return 0;
    }

    @Override
    public int isRunning(String sliceId) {
        if(interruptSignalMap.containsKey(sliceId)){
            return 1;
        }
        if (queue.contains(sliceId)){
            return 0;
        }
        return -1;
    }

    @Override
    public void interrupt(String sliceId) {
        interruptSignalMap.put(sliceId, true);
    }
}
