package net.northking.cctp.device.schedule;

import com.alibaba.fastjson.JSONArray;
import net.northking.cctp.device.api.pcDevice.PcMonitorDataWS;
import net.northking.cctp.device.config.PrometheusConfig;
import net.northking.cctp.device.util.prometheus.*;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
public class MonitorDataSchedule extends QuartzJobBean {

    private final static Logger logger = LoggerFactory.getLogger(MonitorDataSchedule.class);

    @Autowired
    private PcMonitorDataWS socket;

    @Autowired
    private PrometheusConfig prometheusConfig;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        JobDataMap dataMap = context.getMergedJobDataMap();
        HashMap<String, PromSqlDto> map = (HashMap<String, PromSqlDto>) dataMap.get("mapList");
        CopyOnWriteArraySet<PcMonitorDataWS> socketList = (CopyOnWriteArraySet<PcMonitorDataWS>) dataMap.get("socketList");
        for (PcMonitorDataWS ws : socketList) {
            PromSqlDto dto = map.get(ws.getSession().getId());
            String jobName = dto.getJobName();
            String instance = dto.getInstance();
            Session session = dto.getSession();
            int amount = ws.getAmount();
            long step = ws.getStep();
            try {
                List<TargetDto> info = getInfo(jobName,instance,amount,step);
                String result = JSONArray.toJSONString(info);
                session.getBasicRemote().sendText(result);
            } catch (Exception e) {
                logger.error("资源监控异常：jobName:"+jobName+"  instance:"+instance+"  时间:"+amount+"min  间隔"+step+"s");
                throw new RuntimeException("异常信息:",e);
            }
        }
    }

    public List<TargetDto> getInfo(String jobName, String instance,int amount,long step) {
        String queryUrl = PromQlConfig.getQueryRangeUrl(prometheusConfig.getUrl());
        Map<String,String> promQlMap = new LinkedHashMap<>();
        //CPU使用率
        promQlMap.put("cpu使用率",PromQlConfig.windowsCpuRateInstance);
        //内存使用率
        promQlMap.put("内存占用",PromQlConfig.windowsRamRateInstance);
        //网络详情（上传）
        promQlMap.put("network上传",PromQlConfig.networkReceive);
        //网络详情（下载）
        promQlMap.put("network下载",PromQlConfig.networkTransmit);
        //  查询IO read
        promQlMap.put("读取",PromQlConfig.windowsReadInstance);
        // write
        promQlMap.put("写入",PromQlConfig.windowsWriteInstance);
        List<TargetDto> targetDtos = promSqlQuery(jobName, instance, promQlMap, queryUrl,amount,step);
        return targetDtos;
    }

    public List<TargetDto> promSqlQuery(String jobName,String instance,Map<String,String> promQlMap, String queryUrl,int amount,long step){
        List<TargetDto> resultList = new ArrayList<>();
        List<TargetDto> networkInfo = new ArrayList<>();
        List<TargetDto> SCSIInfo = new ArrayList<>();
        for (String key : promQlMap.keySet()) {
            TargetDto dto = new TargetDto();
            String promQl = promQlMap.get(key);
            PrometheusQuery.DataResult info = getResultInfo(jobName, instance, promQl, queryUrl,amount,step);
            if (info!=null) {
                for (List<Object> list : info.getValues()) {
                    Object one = list.get(1);
                    Double d = Double.parseDouble(one.toString());
                    String format = String.format("%.2f", d);
                    list.set(1,format);
                }
            }
            dto.setDataName(key);
            dto.setData(info);
            if (key.equals("network上传") || key.equals("network下载")) {
                networkInfo.add(dto);
            } else if (key.equals("读取") || key.equals("写入")) {
                SCSIInfo.add(dto);
            } else {
                List<TargetDto> targetList = new ArrayList<>();
                TargetDto target = new TargetDto();
                targetList.add(dto);
                if (key.equals("cpu使用率")) {
                    target.setDataName("CPU");
                    target.setUnit("100%");
                } else if (key.equals("内存占用")) {
                    target.setDataName("内存");
                    target.setUnit("100%");
                }
                target.setDataList(targetList);
                resultList.add(target);
            }
        }
        TargetDto network = new TargetDto();
        network.setDataName("网络");
        network.setUnit("kb/秒");
        network.setDataList(networkInfo);

        TargetDto SCSI = new TargetDto();
        SCSI.setDataName("磁盘");
        SCSI.setUnit("kb/秒");
        SCSI.setDataList(SCSIInfo);

        resultList.add(network);
        resultList.add(SCSI);
        return resultList;
    }

    private PrometheusQuery.DataResult getResultInfo(String jobName, String instance, String promQl, String queryUrl,int amount,long step) {
        Date endTime = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(endTime);
        cal.add(Calendar.MINUTE, -amount);
        Date startTime = cal.getTime();

        PrometheusRequest request = new PrometheusRequest();
        request.setStep(step);
        if (promQl.indexOf("$interval") >= 0) {
            promQl = promQl.replaceAll("\\$interval", MonitorTools.getInstance(startTime, endTime));
        }
        request.setQuery(promQl.replaceAll("\\$job", jobName).replaceAll("\\$instance", instance));
        request.setStart(startTime.getTime()/1000 / 15 * 15);
        request.setEnd(endTime.getTime() / 1000 / 15 * 15);
        PrometheusQuery result = PrometheusClient.get(queryUrl, request);
        try {
            List<PrometheusQuery.DataResult> dataResult = result.getData().getResult();
            if (dataResult != null && dataResult.size() > 0 && dataResult.get(0).getValues() != null) {
                return dataResult.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }
}
