package com.jsowell.netty.handler;

import com.google.common.primitives.Bytes;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.core.domain.ykc.YKCDataProtocol;
import com.jsowell.common.core.domain.ykc.YKCFrameTypeCode;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.util.BytesUtil;
import com.jsowell.common.util.CRC16Util;
import com.jsowell.common.util.DateUtils;
import io.netty.channel.Channel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 模板方法模式
 */
public abstract class AbstractHandler implements InitializingBean {

     @Autowired
     private RedisCache redisCache;

     /**
      * 执行逻辑
      * 有应答
      */
     public byte[] supplyProcess(YKCDataProtocol ykcDataProtocol, Channel channel) {
          throw new UnsupportedOperationException();
     }

     /**
      * 执行逻辑
      * 不需要应答
      */
     // public void pushProcess() {
     //      throw new UnsupportedOperationException();
     // }

     /**
      * 组装应答的结果
      * @param ykcDataProtocol 请求数据
      * @param messageBody 消息体
      * @return 应答结果
      */
     protected byte[] getResult(YKCDataProtocol ykcDataProtocol, byte[] messageBody) {
          // 起始标志
          byte[] head = ykcDataProtocol.getHead();
          // 序列号域
          byte[] serialNumber = ykcDataProtocol.getSerialNumber();
          // 加密标志
          byte[] encryptFlag = ykcDataProtocol.getEncryptFlag();
          // 请求帧类型
          byte[] requestFrameType = ykcDataProtocol.getFrameType();
          // 应答帧类型
          byte[] responseFrameType = YKCFrameTypeCode.ResponseRelation.getResponseFrameType(requestFrameType);

          // 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和
          byte[] dataFields = Bytes.concat(serialNumber, encryptFlag, responseFrameType, messageBody);
          // 计算crc： 从序列号域到数据域的 CRC 校验
          int crc16 = CRC16Util.calcCrc16(dataFields);
          return Bytes.concat(head, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16));
     }

     /**
      * 保存桩最后链接到平台的时间
      * @param pileSn 桩编号
      */
     protected void saveLastTime(String pileSn) {
          String redisKey = CacheConstants.PILE_LAST_CONNECTION + pileSn;
          redisCache.setCacheObject(redisKey, DateUtils.getTime(), 60 * 60 * 24);
     }

}