package com.cisdi.data.XRFLEFT.impl;

import com.alibaba.fastjson.JSON;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.gateway.message.SocketMessage;
import com.cisdi.data.sdk.gateway.netty.IoSession;
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
import com.cisdi.data.sdk.service.PassthroughService;
import com.cisdi.data.sdk.service.SendService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 荧光光谱仪左侧解码
 * @author cuianbing
 * @date 2021/7/15 9:19
 * @version 1.0
 */
@Slf4j
public class XRFLeftIoSession extends AbstractIoSession implements IoSession {

    private XRFLeftSessionFactory factory = null;

    private String deviceId = null;
    /**
     * 如果有值，代表所有会话都使用这一个设备id，且允许多会话共享此一个设备id，不除旧会话
     */
    private final String onlyOneDeviceId;

    private String gwPrefixCache = null;

    private ByteBuf allBuf = ByteBufAllocator.DEFAULT.buffer();


    public XRFLeftIoSession(XRFLeftSessionFactory factory, String onlyOneDeviceId) {
        super();
        this.factory = factory;
        this.onlyOneDeviceId = onlyOneDeviceId;
    }

    @Override
    public String[] getDeviceIds() {
        String cpDeviceId = deviceId;
        String[] result = new String[cpDeviceId == null ? 0 : 1];
        if (cpDeviceId != null) {
            result[0] = cpDeviceId;
        }
        return result;
    }

    @Override
    public void onRead(Object message) {
        try {

            ByteBuf inBuf = (ByteBuf) message;
            if (inBuf != null) {
                allBuf.writeBytes(inBuf);
            }else {
                log.info("电文格式为空");
            }
        }catch (Exception e){
            log.error("电文格式错误！");
            throw new BusinessException("电文格式错误！");
        }

    }

    @Override
    public void onOpen() {
        super.onOpen();
        log.info("建立连接，channel:{}", getChannel());
    }

    @Override
    public void onClose() {
        log.info("onClose");
        List<Map<String,String>> messages = decode(allBuf);
        Map<String, Object> sendMessage =new HashMap<>();

        if (serviceProvider != null && socketGateway != null) {
            for (Map<String,String> message : messages){
                sendMessage.put("data",message);
                SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
                SocketMessage socketMessage = socketGateway.buildSocketMessage();
                socketMessage.setDeviceId(onlyOneDeviceId);
                socketMessage.setData(JSON.toJSONString(sendMessage).getBytes(StandardCharsets.UTF_8));
                socketMessage.setMsgKey("default");
                service.sendMessage(socketMessage);
                if (socketGateway.getInstanceVo().getLogOpen()) {
                    log.info("类似为:{}:发送消息内容{}", sendMessage.get("data"), sendMessage.toString());
                }
            }
        }
        super.onClose();
        factory = null;
    }



    public void close() {
        if (getChannel() != null) {
            try {
                getChannel().close().sync();
            } catch (InterruptedException e) {
                log.warn(e.getLocalizedMessage(), e);
            }
        }
    }

    public void onError(Throwable t) {
        // 这里会出现 java.io.IOException: 远程主机强迫关闭了一个现有的连接。
        log.info("远程主机强迫关闭了一个现有的连接。");
//        log.error("session exception:{}", t);
    }


    public List<Map<String,String>> decode(ByteBuf byteBuf){

        List<Map<String,String>> dataList= new ArrayList<>();
        AtomicInteger  dataFlag = new AtomicInteger();
        Map<String,String> data = null;

        String msg = byteBuf.toString(Charset.forName("GB2312"));

        log.debug("{}",msg);
        String[] split = msg.split("\n\r");
        for (String s: split){
            char tag = s.charAt(0);
            if (tag == '3'){
                String[] dataArray = s.split("\\s+");
                if (dataArray.length > 1){   // 分析错误会出现  `3 (Error)   `的数据
                    assert data != null;
                    data.put(dataArray[1],dataArray[2]);
                }
            }else if (tag == '2'){
                if (dataFlag.getAndIncrement() > 0){
                    log.debug("解析的数据为：{}",data);
                    dataList.add(data);
                }
                data = new HashMap<>();
                //2       高炉渣   323      2021- 7-14 15:41 101
                String[] dateArray = s.split("\\s+");
                StringBuilder builder = new StringBuilder();
                // 时间会出现多余空格的问题    2021- 7-14 15:41  ，但是10月之后就可以
                for (int i = 3 , j = dateArray.length - 1 ; i < j ; i++){
                    builder.append(dateArray[i]);
                }
                data.put("分析方法",dateArray[1]);
                data.put("样品名称",dateArray[2]);
                data.put("分析时间",builder.toString());
            }else if(tag == '5'){
                dataList.add(data);
                log.debug("解析的数据为：{}",data);
            }
        }


        allBuf.clear();
        log.info("所有的的数据为：{}",dataList);
        return dataList;
    }


    private void passThrough(ByteBuf passthroughBuf) {
        try {
            if (serviceProvider != null && socketGateway != null) {
                PassthroughService service = (PassthroughService) serviceProvider.getByName(ServiceName.Passthrough);
                service.transfer(passthroughBuf, socketGateway.getInstanceVo().getPassthroughAddress());
            }
        } catch (Exception e) {
            log.error("荧光光谱仪协议透传失败：" + e.getLocalizedMessage(), e);
        }
    }

    public String gwPrefix() {
        if (gwPrefixCache != null) {
            return gwPrefixCache;
        }

        gwPrefixCache = "";
        if (socketGateway != null && socketGateway.getInstanceVo() != null) {
            gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
        } else {
            gwPrefixCache = "连接:" + getChannel() + " ";
        }

        return gwPrefixCache;
    }


}
