package com.jiayue.ipfcst.fileupload.IEC102;

import ch.qos.logback.classic.Logger;
import com.jiayue.ipfcst.common.core.util.SpringContextHolder;
import com.jiayue.ipfcst.common.data.entity.UploadFileChannel;
import com.jiayue.ipfcst.common.data.entity.UploadObject;
import com.jiayue.ipfcst.fileupload.config.AppenderFactory;
import com.jiayue.ipfcst.fileupload.service.UploadFileChannelService;
import com.jiayue.ipfcst.fileupload.service.UploadObjectService;
import com.jiayue.ipfcst.fileupload.util.ByteUtil;
import com.jiayue.ipfcst.fileupload.util.IEC102Uitl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 102解码器
 *
 * @author xsl
 * @version 3.0
 */
@Slf4j
public class ServerFor102Decoder extends SimpleChannelInboundHandler {
  //记录上次未读完的字节
  List<String> messageList = new ArrayList<String>();

  @Autowired
  AppenderFactory appenderFactory = SpringContextHolder.getApplicationContext().getBean(AppenderFactory.class);
  @Autowired
  UploadObjectService uploadObjectService = SpringContextHolder.getApplicationContext().getBean(UploadObjectService.class);
  @Autowired
  UploadFileChannelService uploadFileChannelService = SpringContextHolder.getApplicationContext().getBean(UploadFileChannelService.class);

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
    InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
    // 获取远程IP
    String remoteIP = insocket.getAddress().getHostAddress();
    // 本地IP和端口
    InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
    String localIp = localAddress.getAddress().getHostAddress();
    String localPort = String.valueOf(localAddress.getPort());
    // 根据远端IP获取上报对象报文日志
    List<UploadFileChannel> uploadFileChannelList = uploadFileChannelService.get();
    List<UploadFileChannel> uploadFileChannels = uploadFileChannelList.stream().filter(s -> s.getRemoteIp().equals(remoteIP)).collect(Collectors.toList());
    if (uploadFileChannels.isEmpty()){
      log.error("远端IP:"+remoteIP+"在通道中不存在,不接收对方内容！");
      return;
    }
//    UploadFileChannel uploadFileChannel = uploadFileChannels.get(0);
//    List<UploadObject> uploadObjectList = uploadObjectService.get();
//    UploadObject uploadObject = uploadObjectList.stream().filter(s -> s.getId().equals(uploadFileChannel.getUploadObjectId())).collect(Collectors.toList()).get(0);

    List<UploadObject> tempList = uploadObjectService.get();
    List<UploadObject> uploadObjectList = tempList.stream().filter(s -> s.getUploadProtocolEnum().toString().equals("E1")).collect(Collectors.toList());
    UploadObject uploadObject = null;
    for (UploadFileChannel u:uploadFileChannelList){
      if ((u.getLocalIp()!=null && u.getLocalPort()!=null) && u.getLocalIp().equals(localIp) && u.getLocalPort().equals(localPort) && u.getRemoteIp().equals(remoteIP)){
        for (UploadObject ub:uploadObjectList){
          if (u.getUploadObjectId()==ub.getId()){
            uploadObject = ub;
            break;
          }
        }
      }
    }

    Logger uploadLogger = appenderFactory.getLogger(uploadObject.getUploadObjectName(), uploadObject.getUploadProtocolEnum().getMessage(),uploadObject.getObjectNo());

    try {
      ByteBuf buf = (ByteBuf) msg;
      String receiveStr = ByteBufUtil.hexDump(buf).toUpperCase();
      uploadLogger.info("本次接收报文:"+receiveStr);
      List<String> receivesList = IEC102Uitl.stingToList(receiveStr);
      messageList.addAll(receivesList);

      // 至少6个以上字节才报文解码
      if (messageList.size() >= 6) {
        if (messageList.size()>300){
          // 没用的太多了，舍弃掉
          uploadLogger.info("没用字符串报文超过300个舍弃掉："+messageList.toString());
          messageList.clear();
        }
        else{
          int zb = 0;
          while (true) {
            String nextMessage = "";
            for (int k = 0; k < messageList.size(); k++) {
              if ("10".equals(messageList.get(k)) && (k + 5) <= messageList.size() && messageList.get(k + 5).equals("16")) {
                List newList = messageList.subList(k, (k + 6));
                nextMessage = String.join("", newList);
                String tempStr = String.join("", messageList).substring((k + 6) * 2);
                messageList.clear();
                messageList = IEC102Uitl.stingToList(tempStr);
                break;
              }
              if ("68".equals(messageList.get(k)) && (k + 3) <= messageList.size() && messageList.get(k + 3).equals("68")) {
                int tempLength = ByteUtil.hexToDec(messageList.get(k + 2) + messageList.get(k + 1));
                int end16 = (k + 3) + tempLength + 2;
                if (end16 <= messageList.size() && messageList.get(end16).equals("16")) {
                  List newList = messageList.subList(k, (end16 + 1));
                  nextMessage = String.join("", newList);
                  String tempStr = String.join("", messageList).substring((end16 + 1) * 2);
                  messageList.clear();
                  messageList = IEC102Uitl.stingToList(tempStr);
                  break;
                }
              }
            }
            if (!"".equals(nextMessage)) {
              if (zb==1){
                uploadLogger.info("获取到粘包帧："+nextMessage);
              }
              zb++;
              ctx.fireChannelRead(nextMessage);
            }
            else {
              break;
            }
          }
        }
      }
    }
    catch (Exception e){
      uploadLogger.error("解码失败",e);
    }
  }
}
