package com.zt.plat.module.qms.iot.tcpserver;

import com.zt.plat.module.qms.core.constant.CommonConstant;
import com.zt.plat.module.qms.iot.tcpserver.core.ChannelContextConstant;
import com.zt.plat.module.qms.iot.tcpserver.core.IotDeviceSessionContext;
import com.zt.plat.module.qms.iot.tcpserver.device.RedisSessionComponent;
import com.zt.plat.module.qms.iot.tcpserver.handler.IotClientHandler;
import com.zt.plat.module.qms.iot.tcpserver.handler.IotDeviceHandler;
import com.zt.plat.module.qms.iot.tcpserver.handler.IotHander;
import com.zt.plat.module.qms.iot.tcpserver.handler.IotHeartbeatHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import tech.zzjc.tio.common.starter.annotation.TioServerMsgHandler;
import tech.zzjc.tio.core.ChannelContext;
import tech.zzjc.tio.core.Tio;
import tech.zzjc.tio.http.common.HttpRequest;
import tech.zzjc.tio.http.common.HttpResponse;
import tech.zzjc.tio.websocket.common.WsRequest;
import tech.zzjc.tio.websocket.server.handler.IWsMsgHandler;

import java.nio.charset.Charset;
import java.util.Objects;

/**
 * <b>IotWebSocketMsgHandler</b>
 * <p>
 * 更新历史：
 * <pre> 版本         更新时间            更新者        更新内容<hr/>
 * V1.0      2019年9月18日          王兴荣         Add</pre>
 * <b>Copyright (C)  云南志者竟成科技有限公司</b> 
 * <p>
 * @author 王兴荣 &lt;xingrong_wang@will-way.cn&gt;
 * @version V1.0 
 * @since 2019年9月18日
 */
@Slf4j
@TioServerMsgHandler
public class IotWebSocketMsgHandler implements IWsMsgHandler {

    @Autowired
    private IotClientHandler iotClientHandler;
    
    @Autowired
    private IotDeviceHandler iotDeviceHandler;
    
    @Autowired
    private IotHeartbeatHandler iotHeartbeatHandler;
    @Autowired public RedisSessionComponent redisSessionComponent;

    @Override
    public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        log.info("WebSocket握手");
        return httpResponse;
    }

    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        log.info("WebSocket握手完毕");
//        Map<String, String> headers = httpRequest.getHeaders();
//        for (Map.Entry<String, String> entry : headers.entrySet()) {
//			log.info("请求头：" + entry.getKey() + " = " + entry.getValue());
//		}
        String realClientIp = null;
        String realClientPort = null;
        try {
        	realClientIp = httpRequest.getHeader("x-forwarded-for");
        	realClientPort = httpRequest.getHeader("x-client-port");
            if (StringUtils.isBlank(realClientIp) || CommonConstant.UNKNOWN.equalsIgnoreCase(realClientIp)) {
            	realClientIp = httpRequest.getHeader("X-Real-IP");
            	realClientPort = httpRequest.getHeader("X-Real-PORT");
            }
            if (StringUtils.isBlank(realClientIp) || CommonConstant.UNKNOWN.equalsIgnoreCase(realClientIp)) {
            	realClientIp = httpRequest.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isBlank(realClientIp) || CommonConstant.UNKNOWN.equalsIgnoreCase(realClientIp)) {
            	realClientIp = httpRequest.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isBlank(realClientIp) || CommonConstant.UNKNOWN.equalsIgnoreCase(realClientIp)) {
            	realClientIp = httpRequest.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isBlank(realClientIp) || CommonConstant.UNKNOWN.equalsIgnoreCase(realClientIp)) {
            	realClientIp = httpRequest.getHeader("HTTP_X_FORWARDED_FOR");
            }
        } catch (Exception e) {
        	log.error("IPUtils ERROR ", e);
        }
        log.info("real ip:" + realClientIp);
        if (StringUtils.isNotBlank(realClientIp) && !Objects.equals(realClientIp, channelContext.getClientNode().getIp())) {
//        	Node realNode = new Node(realIp, channelContext.getClientNode().getPort());
//        	realNode.setProtocol("WEB SOCKET");
//        	channelContext.setClientNode(realNode);
//        	channelContext.setProxyClientNode(new Node(channelContext.getClientNode().getIp(), channelContext.getClientNode().getPort()));
        	channelContext.set("realClientIp", realClientIp);
        	channelContext.set("realClientPort", realClientPort);
        	channelContext.set("realClientProtocol", "WebSocket");
        }
    }

    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        return null;
    }

    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        //获取客户端连接信息
        String realClientIp = channelContext.get("realClientIp") == null ? channelContext.getClientNode().getIp() : channelContext.get("realClientIp").toString();
        String realClientPort = channelContext.get("realClientPort") == null ? channelContext.getClientNode().getPort() + "" : channelContext.get("realClientPort").toString();
        String realClient = realClientIp + ":" + realClientPort;
        log.info("WebSocket断开{}", realClient);
        //当前连接的是什么类型客户端
        String connectType = channelContext.get(ChannelContextConstant.CONNECT_TYPE) == null ? "" : channelContext.get(ChannelContextConstant.CONNECT_TYPE).toString();
        switch (connectType) {
            case ChannelContextConstant.CONNECT_CAA_CLIENT:
                //判断是否控制设备,如果控制设备则取消设备控制
                String deviceCode = channelContext.get(ChannelContextConstant.CONTROL_DEVICE_ID) == null ? "" : channelContext.get(ChannelContextConstant.CONTROL_DEVICE_ID).toString();
                if (StringUtils.isNotBlank(deviceCode)) {
                    redisSessionComponent.clearControlByDeviceCode(deviceCode, channelContext);
                }
                break;

            default:
                break;
        }
        return null;
    }

    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        //IotProtocol.handle(text, channelContext);
        IotHander iotHander = null;
        //心跳消息
        if (IotPacket.PING.equalsIgnoreCase(text)) {
            iotHander = iotHeartbeatHandler;
        } else if (text.startsWith("{") && text.endsWith("}")) { //如果是json格式，为客户端协议
            iotHander = iotClientHandler;
        } else { //设备协议
            iotHander = iotDeviceHandler;
        }
        IotPacket iotPacket = new IotPacket();
        iotPacket.setBody(text.getBytes(Charset.forName(IotPacket.CHARSET)));
        iotHander.hander(iotPacket, channelContext);
        return null;
    }

}
