package cn.estsh.i3plus.ext.mes.pcn.apiservice.actor.shipping.strategy;

import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
import cn.estsh.i3plus.mes.pcn.actor.shipping.FiniteStateMachineActor;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.actor.shipping.strategy.IActorReceiveStrategy;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IModuleService;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IWorkCellParamCfgService;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.ICellMonitoringService;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.IShippingDispatchService;
import cn.estsh.i3plus.mes.pcn.config.SpringExtProvider;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
import cn.estsh.i3plus.mes.pcn.websocket.StationWebSocket;
import cn.estsh.i3plus.platform.common.util.MesPcnConstWords;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkModule;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Optional;

//import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmDispatchService;
//import cn.estsh.i3plus.pojo.mes.bean.MesStateMachineStatus;
//import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;
//import java.util.List;

/**
 * 展示组件初始化
 * @author wangjie
 * @date 2020/6/15 09:56
 * @desc
 */
@Slf4j
@Service
public class ActorReceiveStrategyInitExtService implements IActorReceiveStrategy {

    @Autowired
    private ActorSystem actorSystem;

    @Autowired
    private IFsmCommonService fsmCommonService;

//    @Autowired
//    private IFsmDispatchService fsmDispatchService;

    @Autowired
    private IWorkCellParamCfgService workCellParamCfgService;

    @Autowired
    private ICellMonitoringService cellMonitoringService;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    private Boolean islog(StationRequestBean requestBean) {
        if (!StringUtils.isEmpty(requestBean.getWorkCellCode()) &&
                (requestBean.getWorkCellCode().equals("TOP1-116") || requestBean.getWorkCellCode().equals("XWJAZ-055") || requestBean.getWorkCellCode().equals("XWJAF-055")))
            return true;
        else
            return false;
    }

    @Override
    public void exec(StationRequestBean requestBean) {

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR INIT --- START ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //组装缓存与当前的StationRequestBean
        StationRequestBean chReq = fsmCommonService.getCachedStationRequestBean(requestBean);
        if (ObjectUtils.isEmpty(chReq)) {
            chReq = requestBean;
        } else {
            fsmCommonService.assembleReqBeanChangingValue(requestBean, chReq);
        }

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 1 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //获取工位参数
        Map<String, String> wcpcMap = workCellParamCfgService.getWorkCellParamCfgMap(requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 2 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //兼容老流程
        fsmCommonService.packWcpcMapAddRouteCfg(requestBean, wcpcMap);

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 3 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //展示组件初始化
        Optional<IModuleService> moduleService = initModule(chReq, wcpcMap);

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 4 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //校验工位必备参数[LOAD_FSM_ROUTE_TYPE]
        String loadType = fsmCommonService.getAndCheckWcpcMapIsContainsKey(chReq, wcpcMap, MesPcnConstWords.LOAD_FSM_ROUTE_TYPE);
        if (moduleService.isPresent() && !StringUtils.isEmpty(loadType)) {
            //初始化监听组件
            Boolean isMonitor = initCellMonitor(chReq, moduleService.get());

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 5 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            if (!isMonitor) {

                if (islog(requestBean))
                    log.info("工厂{}生产线{}工位{}:ACTOR INIT --- 6 ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

                //没有监听组件时, 自动加载状态机
                triggerAutoFsm(chReq, wcpcMap);
            }
        }
        fsmCommonService.putStationRequestBean(chReq, "ActorReceiveStrategyInitService");
    }

    /**
     * 展示组件初始化
     *
     * @param requestBean
     */
    private Optional<IModuleService> initModule(StationRequestBean requestBean, Map<String, String> wcpcMap) {
        //校验工位必备参数[MODULE_OBJECT]
        String moduleObject = fsmCommonService.getAndCheckWcpcMapIsContainsKey(requestBean, wcpcMap, MesPcnConstWords.MODULE_OBJECT);
        if (StringUtils.isEmpty(moduleObject)) {
            return Optional.empty();
        }
        //缓存工位参数信息
        fsmCommonService.putWorkCellParam(requestBean, wcpcMap);
        requestBean.setWcpcMap(wcpcMap);
        IModuleService moduleService = (IModuleService) SpringContextsUtil.getBean(wcpcMap.get(MesPcnConstWords.MODULE_OBJECT));
        if (null == moduleService) {
            String msg = LocaleUtil.transferLanguage(requestBean.getUserInfo(), "工作单元参数{ModuleObject}维护的生产组件无效!");
            StationWebSocket.sendMessage(requestBean, msg, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return Optional.empty();
        }
        moduleService.init(requestBean);
        return Optional.of(moduleService);
    }

    /**
     * 初始化监听组件
     *
     * @param reqBean
     * @param moduleService
     */
    public Boolean initCellMonitor(StationRequestBean reqBean, IModuleService moduleService) {
        String triggerKey = fsmCommonService.getFsmCacheKey(reqBean, MesPcnConstWords.ACTOR_MSG_DISPATCHER_NAME, MesPcnConstWords.SHIPPING_ACTOR_SUFFIX);
        String allowStartKey = fsmCommonService.getFsmCacheKey(reqBean, MesPcnConstWords.ALLOW_START_MONITOR, MesPcnConstWords.SHIPPING_ACTOR_SUFFIX);
        if (null == FiniteStateMachineActor.getDispatcherMap(triggerKey)) {
            ActorRef ref;
            synchronized (FiniteStateMachineActor.class) {
                //获取作业程序组件(监听类型)
                MesWorkModule workModule = cellMonitoringService.getWorkModule(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());
                if (null == workModule || StringUtils.isEmpty(workModule.getCallClass())) {
                    return false;
                }
                if (null == FiniteStateMachineActor.getDispatcherMap(triggerKey)) {
                    ref = actorSystem.actorOf(SpringExtProvider.getInstance().get(actorSystem).create(MesPcnConstWords.ACTOR_MSG_DISPATCHER_NAME), triggerKey);
                    FiniteStateMachineActor.putDispatcherMap(triggerKey, ref);
                } else {
                    ref = FiniteStateMachineActor.getDispatcherMap(triggerKey);
                }
                if (ref == null) {
                    return false;
                }
                reqBean.setMonitorModule(workModule.getCallClass());
                reqBean.setMonitorMsg(MesPcnConstWords.START);
                reqBean.setModuleService(moduleService);
                ref.tell(reqBean, ActorRef.noSender());
                FiniteStateMachineActor.putAllowStartMonitorMap(allowStartKey);   // 设置不允许开启监听
                return true;
            }
        } else {
            if (FiniteStateMachineActor.getAllowStartMonitorMap(allowStartKey) == null) {
                startCellMonitor(reqBean, moduleService);   // 开启监听
                FiniteStateMachineActor.putAllowStartMonitorMap(allowStartKey);   // 设置不允许开启监听
            }
            return true;
        }
    }

    /**
     * 启动监听组件
     *
     * @param requestBean
     * @param moduleService
     */
    private void startCellMonitor(StationRequestBean requestBean, IModuleService moduleService) {
        String selectionKey = fsmCommonService.getFsmCacheKey(requestBean, MesPcnConstWords.ACTOR_MSG_DISPATCHER_NAME, MesPcnConstWords.SHIPPING_ACTOR_SUFFIX);
        ActorSelection actorSelection = actorSystem.actorSelection("/user/" + selectionKey);
        //获取作业程序组件(监听类型)
        MesWorkModule workModule = cellMonitoringService.getWorkModule(requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());
        if (workModule == null) {
            return;
        }
        requestBean.setMonitorModule(workModule.getCallClass());
        requestBean.setMonitorMsg(MesPcnConstWords.START);
        requestBean.setModuleService(moduleService);
        try {
            actorSelection.tell(requestBean, ActorRef.noSender());
        } catch (Exception ex) {
            log.error("startMonitor 发生异常:{}, 入参:{} ", ex.getMessage(), requestBean);
        }
    }

    public void triggerAutoFsm(StationRequestBean chReq, Map<String, String> wcpcMap) {
        if (wcpcMap.get(MesPcnConstWords.LOAD_FSM_ROUTE_TYPE).equals(MesPcnEnumUtil.LOAD_FSM_ROUTE_TYPE.BY_AUTO.getValue())) {
            /*//根据工位参数配置获取状态机流程
            List<MesStateMachineStatus> statuses = fsmCommonService.getFsmRouteStatus(chReq);
            //校验状态机流程的有效性
            if (!fsmCommonService.checkFsmValid(chReq, statuses)) return;
            //初始化状态机
            UntypedStateMachineBuilder stateMachineBuilder = FiniteStateMachineActor.buildFsm(chReq.getUserInfo(), statuses);
            //封装流程工序状态机到StationRequestBean
            fsmCommonService.packChReqRouteProcessState(chReq, statuses);
            if (null == chReq.getCurFsmState()) {
                Optional<MesStateMachineStatus> notCompleteState = fsmCommonService.getFirstState(chReq.getFsmStates());
                if (notCompleteState.isPresent()) {
                    chReq.setCurFsmState(fsmCommonService.copyFsmState(notCompleteState.get()));
                }
            }
            fsmDispatchService.fireStateMachine(stateMachineBuilder, fsmCommonService.getFsmCacheKey(chReq), chReq);*/

            //2021-05-20 变更逻辑 ： 通过DO_SCAN触发状态机
            chReq.setClientInfo(shippingDispatchService.getActorClientInfo(chReq));
            chReq.setInterfaceType(MesPcnConstWords.SHIPPING);
            chReq.setBusiType(MesPcnConstWords.WS_CMD_DO_SCAN);
            chReq.setTriggerAutoFsm(true);
            shippingDispatchService.doSendScanQueueIfNoQueue(chReq);
        }
    }

}
