package org.gyk.modules.sssj.util;


import KHThrift.*;
import org.apache.thrift.TApplicationException;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.transport.TTransportException;
import org.gyk.modules.sssj.entity.GykDataProperties;
import org.gyk.modules.sssj.service.ISaveBjlsService;
import org.gyk.modules.sssj.service.ISaveJldlsService;
import org.gyk.modules.sz.bjpz.mapper.CxcSssjSzBjszMapper;
import org.gyk.modules.sz.jldxx.service.ICxcSssjSzJldxxService;
import org.gyk.modules.sz.jldxx.service.IGetJldxxService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * @Description: 计量点实时数据方法
 * @Author: liao
 * @Date:   2021-04-05
 * @Version: V1.0
 */
//@Cacheable
//@Log4j
@Component
public class KDBClient {
    public static KDBApi m_Client = new KDBApi();
    public static List<String> tageNames = new ArrayList<>();
//    static CacheManager manager = CacheManager.getInstance();
//    public static Cache cacheKHData;
//    static ResourceBundle RESOURCE_BUNDLE;
    public static long KHServerTime;
    public static List<String> AllName = new ArrayList<>();
    public static Map<String, String> map_res = new HashMap<>();
    public static List<GykDataProperties> AllJldProperties = new ArrayList<>();
    public static Map<String,String> map_yasuoji = new HashMap<>();

    @Autowired
    private IGetJldxxService getJldXxService;
    @Autowired
    private ISaveJldlsService saveJldlsService;
    @Resource
    private CxcSssjSzBjszMapper bjszMapper;
    @Autowired
    private ISaveBjlsService saveBjlsService;
    public static KDBClient judge;
    public KDBClient() {
    }
    @PostConstruct
    public void init(){
        judge = this ;
        judge.getJldXxService = this.getJldXxService;
        judge.saveJldlsService = this.saveJldlsService;
        judge.bjszMapper = this.bjszMapper;
        judge.saveBjlsService = this.saveBjlsService;
    }
    @Value("${KH.ServerName}")
    private String KH_ServerName;
    @Value("${KH.ServerPort}")
    private int KH_ServerPort;
    @Value("${KH.UserName}")
    private String KH_UserName;
    @Value("${KH.Password}")
    private String KH_Password;
    @Value("${KH.NetworkTimeout}")
    private int KH_NetworkTimeout;
    private static String KH_ServerName1;
    private static int KH_ServerPort1;
    private static String KH_UserName1;
    private static String KH_Password1;
    private static int KH_NetworkTimeout1;
    @PostConstruct
    public void setServe() {
        KH_ServerName1 = this.KH_ServerName;
        KH_ServerPort1 = this.KH_ServerPort;
        KH_UserName1 = this.KH_UserName;
        KH_Password1 = this.KH_Password;
        KH_NetworkTimeout1 = this.KH_NetworkTimeout;
    }
    @Autowired
    private  ICxcSssjSzJldxxService cxcSssjSzJldxxService;

    private static Logger log = LoggerFactory.getLogger(KDBClient.class);

    //连接工业库-实时数据库
    public static boolean KDBServerConnect() {
        ThriftConnectOption ConnOption = new ThriftConnectOption();
        ConnOption.ServerName = KH_ServerName1;
        ConnOption.ServerPort = KH_ServerPort1;
        ConnOption.UserName = KH_UserName1;
        ConnOption.Password = KH_Password1;
        ConnOption.NetworkTimeout = KH_NetworkTimeout1;
        KHServerTime = 0L;
        ThriftConnectRet Ret = null;

        try {
            Ret = m_Client.KDBServerConnect(ConnOption);
            if (Ret.Ret == 0) {
                log.info("实时数据库 KDBServerConnect-连接成功");
                return true;
            }
            log.error( "实时数据库 KDBServerConnect" + Ret);
            return false;
        } catch (TTransportException var3) {
            log.error( "实时数据库 KDBServerConnect" + Ret);
            var3.printStackTrace();
        } catch (TException var4) {
            var4.printStackTrace();
        }
        return false;
    }
    //判断工业库-实时数据库是否连接
    public static boolean KDBServerIsConnected(int count) {
        boolean KDBServerIsConnected = false;
        byte counNum = 20;

        try {
            KDBServerIsConnected = m_Client.KDBServerIsConnected();
            if (KDBServerIsConnected) {
                return true;
            } else {
                log.error("实时数据库 KDBServerIsConnected-未连接");
                return KDBServerConnect();
            }
        } catch (TTransportException var4) {
            KDBServerRsconnect();
            log.error("实时数据库 KDBServerIsConnected-异常:TProtocolException");
            return count == counNum ? false : KDBServerIsConnected(count + 1);
        } catch (TProtocolException var5) {
            KDBServerRsconnect();
            log.error("实时数据库 KDBServerIsConnected-异常:TProtocolException");
            return count == counNum ? false : KDBServerIsConnected(count + 1);
        } catch (TApplicationException var6) {
            KDBServerRsconnect();
            log.error("实时数据库 KDBServerIsConnected-异常:TApplicationException");
            return count == counNum ? false : KDBServerIsConnected(count + 1);
        } catch (Exception var7) {
            KDBServerRsconnect();
            var7.printStackTrace();
            log.error("实时数据库 KDBServerIsConnected-异常");
            return count == counNum ? false : KDBServerIsConnected(count + 1);
        }
    }
    //判断工业库-服务器是否连接
    public static boolean ServerIsConnected() {
        boolean KDBServerIsConnected = false;

        try {
            KDBServerIsConnected = m_Client.KDBServerIsConnected();
            if (KDBServerIsConnected) {
                return true;
            } else {
                log.error("实时数据库 KDBServerIsConnected-未连接");
                return false;
            }
        } catch (TTransportException var4) {
            log.error("实时数据库 KDBServerIsConnected-异常:TProtocolException");
            return false;
        } catch (TProtocolException var5) {
            log.error("实时数据库 KDBServerIsConnected-异常:TProtocolException");
            return false;
        } catch (TApplicationException var6) {
            log.error("实时数据库 KDBServerIsConnected-异常:TApplicationException");
            return false;
        } catch (Exception var7) {
            //var7.printStackTrace();
            log.error("实时数据库 KDBServerIsConnected-异常");
            return false;
        }

    }
    //将工业库-实时数据库重启连接
    public static void KDBServerRsconnect() {
        int Ret = 0;

        try {
            Ret = m_Client.KDBServerDisconnect();

            if (Ret == 0) {
                log.info("实时数据库 KDBServerDisconnect-关闭成功");
            } else {
                log.error("实时数据库 KDBServerDisconnect" + Ret);
            }
        } catch (TProtocolException var2) {
            log.error("实时数据库 KDBServerDisconnect" + Ret);
            var2.printStackTrace();
        } catch (TException var3) {
            var3.printStackTrace();
        }
        KDBServerConnect();
    }
    //关闭工业库-实时数据库
    static void KDBServerDisconnect() {
        int Ret = 0;

        try {
            Ret = m_Client.KDBServerDisconnect();
            if (Ret == 0) {
                log.info("实时数据库 KDBServerDisconnect-关闭成功");
            } else {
                log.error("实时数据库 KDBServerDisconnect" + Ret);
            }
        } catch (TProtocolException var3) {
            log.error("实时数据库 KDBServerDisconnect" + Ret);
            var3.printStackTrace();
        } catch (TException var4) {
            var4.printStackTrace();
        }
    }
    //获取“工业库”所有计量点（变量）名称
    public static void KDBTagGetAllNames() {
        long newtime = System.currentTimeMillis();
        if (KDBServerIsConnected(0)) {
            try {
                ThriftTagGetNamesRet Ret = m_Client.KDBTagGetAllNames();
                AllName = Ret.TagNames;

                if (Ret.Ret == 0) {
                    tageNames = Ret.TagNames;
                } else {
                    System.out.println(String.format("Get tag all names failed:%d", Ret.Ret));
                }
            } catch (TException var3) {
                var3.printStackTrace();
            }
        }
    }
    //获取每个计量点属性：所属的单位、站场和计量点名称
    public static void KDBTagGetZhanc(List<String> TagNames) throws TException {
        if (KDBServerIsConnected(0)) {
            ThriftTagFields TagFields = new ThriftTagFields();
//         TagFields表示属性配置  ，额外传参数
            TagFields.TagName = true;
            TagFields.TagId = true;
            TagFields.EngineeringUnit = true;
            TagFields.UserGeneral5 = true;
            TagFields.UserGeneral6 = true;
            TagFields.UserGeneral7 = true;

            List<GykDataProperties> AllJld = new ArrayList<>();

            if (TagNames.size() > 0) {   //对传来的计量点列表进行判断
                TagNames.forEach(item -> {   //遍历TagNames
                    ThriftTagGetPropertiesRet Ret = null;
                    try {
                        Ret = m_Client.KDBTagGetProperties(item.toString(), TagFields);
                        if (Ret.Ret == 0) {
                            ThriftTagProperties ttgp = Ret.TagProperties;
//                           log.info(" "item:"+item+"单位：" + ttgp.UserGeneral5 + " 站场：" + ttgp.UserGeneral6+"other:"+ttgp.UserGeneral7);
                            GykDataProperties JldCs = new GykDataProperties(item, ttgp.TagId,ttgp.UserGeneral5, ttgp.UserGeneral6, ttgp.UserGeneral7,ttgp.EngineeringUnit);
                            AllJld.add((JldCs));
                        }
                    } catch (TException e) {
                        e.printStackTrace();
                    }
                });
//                将带属性的AllJld按管理区、站场分组，这里不再需要，分组已用jldxx表实现
//                AllJldProperties = AllJld.stream().sorted(Comparator.comparing(GykDataProperties::getQu).thenComparing(GykDataProperties::getZhan)).collect(Collectors.toList());
                  AllJldProperties = AllJld;
            }
        }
    }
    //修正时区，获得正确时间参数
    public static String timeToStr(long num) {
        String time = "";
        String pattern = "yyyy-MM-dd HH:mm:ss";
        //使用的时区都是东8区，也就是北京时间。这是为了防止服务器设置时区错误时导致时间不对，如果您是其他时区，请自行修改
        LocalDateTime dateTime = LocalDateTime.ofEpochSecond(num, 0, ZoneOffset.ofHours(8));
        time = dateTime.format(DateTimeFormatter.ofPattern(pattern));
        return time;
    }
    //获取“工业库”实时数据+值+属性
    public static synchronized void KDBDataGetCurrentValue(List<String> TagNames) {
        if (KDBServerIsConnected(0)) {
//          参数属性设置为真
            ThriftTagFields TagFields = new ThriftTagFields();
            TagFields.AllFields = true;
//          每次调用清缓存map_res
//            map_res.clear();//2020-09-17

            try {
                ThriftDataGetCurrentValueRet Ret = m_Client.KDBDataGetCurrentValue(TagNames);
                if (Ret.Ret == 0) {
                    List<KDBDataProperties> r = KDBConvert.Convert(Ret.DataProperties);
//                  把参数对应的每个属性，都加入map_res
                    for (int n = 0; n < r.size(); ++n) {
//                      log.info("name:"+(String)TagNames.get(n)+" value:"+getValue((KDBDataProperties)r.get(n)));
                        map_res.put((String) TagNames.get(n), getValue((KDBDataProperties) r.get(n)));
                    }

                    int getTime1 = m_Client.KDBServerGetTime().CurrentTime.Seconds;
//                  log.info("GYK server time: " + timeToStr(getTime1));

                } else {
                    System.out.println(String.format("Data get current value failed:%d", Ret));
                }
            } catch (TException var8) {
                var8.printStackTrace();
            }
        }
    }
    // 获得所有计量点+数据的map
    public static Map MapJldData() throws InterruptedException {

        Map<Integer, String> AllJldMap = null;

        try {
            Map<String,String> map_res_jl = new HashMap<>();
//      以防map_res每次清空时，显示空值，使其延时0.1m
            while (map_res.size()<1) {
                //MILLISECONDS表示以毫秒为单位延时
                TimeUnit.MILLISECONDS.sleep(1000);
            }
//      重新存储一个map，使读取数据时确定一个数据表，不会出现前后混乱
            map_res_jl.putAll(map_res);

            //对筛选出的List表，从map_jl中获取对应的计量点的值
            AllJldProperties.forEach(item -> {
                String val = map_res_jl.get(item.getTagName());

                if (!val.isEmpty()) {
                    item.setvalue( val);
                } else {
                    item.setvalue("0");
                }
            });
            AllJldMap = AllJldProperties.stream().collect(
                    Collectors.toMap(GykDataProperties::getTagId,GykDataProperties::getvalue));


        } catch (Exception e) {
            e.printStackTrace();
        }
        return  AllJldMap;
    }
    // 获得参数对应属性中的value值，KDBDataGetCurrentValue接口中调用【不懂value值来源？？】
    public static String getValue(KDBDataProperties KDBDataProperties) {
        String rls = "-";
        switch (KDBDataProperties.Value.DataType) {
            case 0:
                rls = String.valueOf(KDBDataProperties.Value.Value.emptyVal);
                break;
            case 1:
                rls = String.valueOf(KDBDataProperties.Value.Value.bitVal);
                break;
            case 2:
                rls = String.valueOf(KDBDataProperties.Value.Value.i1Val);
                break;
            case 3:
                rls = String.valueOf(KDBDataProperties.Value.Value.ui1Val);
                break;
            case 4:
                rls = String.valueOf(KDBDataProperties.Value.Value.i2Val);
                break;
            case 5:
                rls = String.valueOf(KDBDataProperties.Value.Value.ui2Val);
                break;
            case 6:
                rls = String.valueOf(KDBDataProperties.Value.Value.i4Val);
                break;
            case 7:
                rls = String.valueOf(KDBDataProperties.Value.Value.ui4Val);
                break;
            case 8:
                rls = String.valueOf(KDBDataProperties.Value.Value.i8Val);
                break;
            case 9:
                rls = String.valueOf(KDBDataProperties.Value.Value.ui8Val);
                break;
            case 10:
                rls = String.valueOf(KDBDataProperties.Value.Value.r4Val);
                break;
            case 11:
                rls = String.valueOf(KDBDataProperties.Value.Value.r8Val);
                break;
            case 12:
                rls = KDBDataProperties.Value.Value.strVal;
                break;
            case 13:
                rls = KDBDataProperties.Value.Value.wstrVal;
                break;
            case 14:
                rls = "" + KDBDataProperties.Value.Value.tsVal;
                break;
            case 15:
                rls = "" + KDBDataProperties.Value.Value.blobVal;
            case 16:
            default:
                break;
            case 17:
                rls = String.valueOf(KDBDataProperties.Value.Value.ftVal);
                break;
            case 18:
                rls = "" + KDBDataProperties.Value.Value.decVal;
        }

        return rls;
    }

}

