package com.gyee.alarm.service;


import com.gyee.alarm.feigns.IAlarmService;
import com.gyee.alarm.init.CacheContext;
import com.gyee.alarm.model.auto.ProBasicEquipmentPoint;
import com.gyee.alarm.model.vo.*;
import com.gyee.alarm.rule.AlarmFunction;
import com.gyee.alarm.rule.expression.AlarmExpression;
import com.gyee.alarm.rule.expression.Analyzer;
import com.gyee.alarm.service.auto.IAlarmTsService;
import com.gyee.alarm.task.thread.AlarmThread;
import com.gyee.alarm.task.thread.ReadWtDataThread;
import com.gyee.alarm.util.realtimesource.IEdosUtil;
import com.gyee.common.model.PointData;
import com.gyee.common.model.StringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;


@Service
@Slf4j
public class CustomAsyncService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());





    @Async("taskExecutor")
    public CompletableFuture<String> readCall(IEdosUtil edosUtil, Integer readRows, List<ProBasicEquipmentPoint> pointList,String str) throws Exception {

        Integer result = 1;

        try {

            List<String>  ls=new ArrayList<>();
            List<PointData> values=new ArrayList<>();

            int times=0;
            for(ProBasicEquipmentPoint vo:pointList)
            {
                ls.add(vo.getNemCode());
                times++;
                if(times==readRows)
                {
                    List<PointData> templs=edosUtil.getRealData(ls);
                    values.addAll(templs);
                    ls=new ArrayList<>();
                    times=0;
                }
            }
            if(!ls.isEmpty())
            {
                List<PointData> templs=edosUtil.getRealData(ls);
                values.addAll(templs);
            }

            if(values.size() == pointList.size())
            {

                for(int i=0;i<pointList.size();i++)
                {
                    ProBasicEquipmentPoint point=pointList.get(i);
                    PointData value=values.get(i);
                    if(CacheContext.wtDataValueMap.containsKey(point.getWindturbineId()))
                    {
                        Map<String, PointData> map=CacheContext.wtDataValueMap.get(point.getWindturbineId());
                        map.put(point.getUniformCode(),value);
                    }else
                    {
                        Map<String, PointData> map=new HashMap<>();

                        map.put(point.getUniformCode(),value);
                        CacheContext.wtDataValueMap.put(point.getWindturbineId(),map);
                    }
                }
            }



        } catch (Exception e) {

            e.printStackTrace();
            result=0;
        }


        return CompletableFuture.completedFuture(str+"Task completed");

    }




    @Async("taskExecutor")
    public CompletableFuture<String>  checkCall(IAlarmService alarmService, List<AlarmCustomTag> alarmVoList,
                                     StringBuilder str, Integer readRows, IAlarmTsService alarmTsService) throws Exception {

        Integer result = 1;

        try {



            List<AlarmTag> saveAlarmTags =   new CopyOnWriteArrayList<>();
            List<AlarmTag> updateAlarmTags  = new CopyOnWriteArrayList<>();


            StringBuilder sb = new StringBuilder();


            List<AlarmSimpleVo> alarmls = new CopyOnWriteArrayList<>();
            int times = 0;
            for (AlarmCustomTag alarm : alarmVoList) {

                sb.append("'").append(alarm.getId().toLowerCase()).append("',");
                times++;
                if (times == readRows) {
                    String ids =  sb.substring(0, sb.length() - 1);
                    List<AlarmSimpleVo>  templs=new ArrayList<>();
                    templs =  alarmTsService.selectLastRowByTbname(AlarmSuperTalbeType.CT.getCode(), ids);
                    alarmls.addAll(templs);
                    sb.setLength(0);
                    times = 0;
                }
            }
            if (sb.length()>0) {

                String ids =  sb.substring(0, sb.length() - 1);
                List<AlarmSimpleVo>  templs=new ArrayList<>();
                templs =  alarmTsService.selectLastRowByTbname(AlarmSuperTalbeType.CT.getCode(), ids);
                alarmls.addAll(templs);
            }

            Map<String, AlarmSimpleVo> map = new ConcurrentHashMap<>();


            if (!alarmls.isEmpty()) {
                for (AlarmSimpleVo vo : alarmls) {
                    map.put(vo.getTbName().toLowerCase(), vo);
                }
            }


            for (AlarmCustomTag vo : alarmVoList) {

                checkRule(saveAlarmTags, updateAlarmTags, vo,map);

            }

            if (!saveAlarmTags.isEmpty()) {
                alarmService.saveAlarm(saveAlarmTags);
            }

            if (!updateAlarmTags.isEmpty()) {
                alarmService.updateAlarm(updateAlarmTags);
            }



            logger.info(str+ "新增报警数量：" + saveAlarmTags.size());
            logger.info(str+ "结束报警数量：" + updateAlarmTags.size());
        } catch (Exception e) {

            e.printStackTrace();

        }


        return CompletableFuture.completedFuture(str+"Task completed");

    }

    private  void checkRule(List<AlarmTag> saveAlarmTags, List<AlarmTag> updateAlarmTags, AlarmCustomTag ar,Map<String, AlarmSimpleVo> map) {


        try {

            AlarmExpression alarmExpression = Analyzer.getAlarmExpression(ar.getTagId());

            AlarmFunction alarmFunction = null;

            if (ar.getDevicetype().equals(DeviceTypeValue.WT.getCode())) {
                alarmFunction = new AlarmFunction(alarmExpression, DeviceTypeValue.WT, ar.getDeviceid());


            }else if (ar.getDevicetype().equals(DeviceTypeValue.IN.getCode())) {
                alarmFunction = new AlarmFunction(alarmExpression, DeviceTypeValue.IN, ar.getDeviceid());


            } else if (ar.getDevicetype().equals(DeviceTypeValue.BT.getCode())) {
                alarmFunction = new AlarmFunction(alarmExpression, DeviceTypeValue.BT, ar.getStationid());
            }

            try {

                Object obj = alarmFunction.explain();

                if (obj instanceof Boolean) {


                    boolean endStatus = true;

                    if(map.containsKey(ar.getId().toLowerCase()))
                    {
                        AlarmSimpleVo vo=map.get(ar.getId().toLowerCase());

                        if(StringUtils.notEmp(vo.getEndts()))
                        {
                            endStatus=true;
                        }else
                        {
                            endStatus=false;
                        }
                    }else
                    {
                        endStatus = true;
                    }
                    if (true == (boolean) obj) {

                        if(endStatus)
                        {
                            AlarmTag po = new AlarmTag();
                            po.setId(ar.getId());
                            po.setTs(new Date().getTime());
                            po.setEndts(null);
                            po.setVal(1.0);
                            po.setOval(1.0);
                            po.setTimeLong(0.0);

                            saveAlarmTags.add(po);
                        }

                    } else {

                        if(!endStatus)
                        {
                            AlarmTag po = new AlarmTag();
                            po.setId(ar.getId());
                            po.setTs(new Date().getTime());
                            po.setEndts(new Date().getTime());
                            po.setVal(0.0);
                            po.setOval(0.0);
                            po.setTimeLong(0.0);

                            updateAlarmTags.add(po);
                        }

                    }
                } else {
                    // System.out.print(obj.toString());
                }
            } catch (Exception ex) {
                // ex.printStackTrace();
                logger.error("自定义报警规则执行时出错！" + alarmFunction.getThingId() + "--" + ar.getTagId() + "----" + ex.getMessage());
            }

        } catch (Exception ex) {
            logger.error("生成自定义报警规则失败！规则id：" + ar.getId());
        }
    }
}
