package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.busi.bu3;

import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxProdDataToSoftAdapterStrategyService;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxProdDataToSoftAdapterCfgModel;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxProdDataToSoftAdapterDataModel;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class SxProdDataToSoftAdapterStrategyDispatchService implements ISxProdDataToSoftAdapterStrategyService {

    public SxProdDataToSoftAdapterStrategyDispatchService() {}

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = {ImppBusiException.class,Exception.class})
    public SxProdDataToSoftAdapterDataModel exec(SxProdDataToSoftAdapterDataModel data) {

        log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- DISPATCH START --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), data.getCurrentThreadName());

        ISxProdDataToSoftAdapterStrategyService strategyService = instanceStrategyService(data, data.getStrategyClass(), null);

        if (null == strategyService) return data;

        log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- QUERY START --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), data.getCurrentThreadName());

        data = strategyService.query(data);

        if (null == data.getObj())
            log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- QUERY ERROR --- RESULT LIST IS NULL --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), data.getCurrentThreadName());
        else log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- QUERY END --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), data.getCurrentThreadName());

        if (null != data.getObj()) instanceObserver(data).exec(data);

        log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- DISPATCH END --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), data.getCurrentThreadName());

        return data;

    }

    private Observer instanceObserver(SxProdDataToSoftAdapterDataModel data) {
        Observer observer = new Observer();
        for (SxProdDataToSoftAdapterCfgModel cfgModel : data.getCfgModelList()) {
            if (null == cfgModel) continue;
            observer.add(instanceStrategyService(data, StringUtils.isEmpty(cfgModel.getExecClass()) ? cfgModel.getStrategyClass() : cfgModel.getExecClass(), cfgModel));
        }
        return observer;
    }

    private ISxProdDataToSoftAdapterStrategyService instanceStrategyService(SxProdDataToSoftAdapterDataModel data, String strategyClass, SxProdDataToSoftAdapterCfgModel cfgModel) {

        try {

            Class clazz = Class.forName(strategyClass);

            Constructor constructor = clazz.getConstructor(ISxProdDataToSoftAdapterStrategyService.class, SxProdDataToSoftAdapterCfgModel.class);

            ISxProdDataToSoftAdapterStrategyService strategyService = (ISxProdDataToSoftAdapterStrategyService) constructor.newInstance(Class.forName(MesExtConstWords.IOT_COMMON_STRATEGY).newInstance(), cfgModel);

            return strategyService;

        } catch (Exception e) {

            log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- DISPATCH ERROR:[{}] --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), e.getMessage(), data.getCurrentThreadName());

            return null;

        }
    }

    class Observer {

        private List<ISxProdDataToSoftAdapterStrategyService> strategyServiceList;

        public Observer() {}

        public void add(ISxProdDataToSoftAdapterStrategyService strategyService) {
            if (null == strategyService) return;
            if (CollectionUtils.isEmpty(strategyServiceList)) strategyServiceList = new ArrayList<>();
            strategyServiceList.add(strategyService);
        }

        public void exec(SxProdDataToSoftAdapterDataModel data) {

            if (CollectionUtils.isEmpty(strategyServiceList)) return;

            for (ISxProdDataToSoftAdapterStrategyService strategyService : strategyServiceList) {
                if (null == strategyService) continue;

                try {

                    log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- EXEC_CLASS[{}] --- EXEC START --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), strategyService.getCfgModel().getClassName(), data.getCurrentThreadName());

                    Object obj = strategyService.exec(data);

                    if (null == obj) {
                        log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- EXEC_CLASS[{}] --- EXEC RESULT LIST IS NULL --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), strategyService.getCfgModel().getClassName(), data.getCurrentThreadName());
                        continue;
                    }

                    strategyService.getStrategyService().doInvokeSuit(data, obj, strategyService.getCfgModel());

                    log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- EXEC_CLASS[{}] --- EXEC END --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), strategyService.getCfgModel().getClassName(), data.getCurrentThreadName());

                } catch (Exception e) {
                    log.info("MES工厂{}DATE{}执行生产数据回传软适配JOB --- EXEC STRATEGY_CLASS[{}] --- EXEC_CLASS[{}] --- EXEC ERROR:[{}] --- THREAD:[{}]", data.getOrganizeCode(), data.getDate(), data.getClassName(), null == strategyService.getCfgModel() ? null : strategyService.getCfgModel().getClassName(), e.getMessage(), data.getCurrentThreadName());
                }
            }
        }
    }

}
