package com.cisdi.data.IDCardReader.gateway.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cisdi.data.IDCardReader.gateway.vo.IDCardVo;
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineConfigVo;
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineResponseVo;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.gateway.Gateway;
import com.cisdi.data.sdk.gateway.base.GatewayBase;
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
import com.cisdi.data.sdk.gateway.message.SocketMessage;
import com.cisdi.data.sdk.service.SendService;
import com.cisdi.data.sdk.service.ServiceProvider;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicBoolean;

public class ZKIDROnlineListener extends WebSocketClient {

    private Integer reconnectCount=0;

    private String runId;
    private String deviceId;
    private Boolean autoReconnect=false;
    private Long reconnectDelay =1000L;
    private ServiceProvider serviceProvider=null;
    private SocketGatewayBase socketGatewayBase=null;
    private Logger logger= LoggerFactory.getLogger(ZKIDROnlineListener.class);
    private ZKIDROnlineConfigVo zkidrOnlineConfigVo=null;
    private Boolean startFlag=false;
    private static final String  SUCCESS_STR="BeginReadCard Succsefull";
    private AtomicBoolean shouldRun=new AtomicBoolean(true);

    public void setShouldRun(boolean b)
    {
        shouldRun.set(b);
    }

    public ZKIDROnlineListener(URI serverUri,
                               String deviceId,
                               SocketGatewayBase socketGateway,
                               ServiceProvider serviceProvider,
                               ZKIDROnlineConfigVo zkidrOnlineConfigVo) {
        super(serverUri);
        if(socketGateway!=null)
        {
            this.runId=socketGateway.getInstanceVo().getRunId();
        }
        if(zkidrOnlineConfigVo!=null)
        {
            this.autoReconnect=zkidrOnlineConfigVo.getAutoReconnect();
            this.reconnectDelay =zkidrOnlineConfigVo.getReconnectDelay();
        }
        this.deviceId=deviceId;
        this.socketGatewayBase=socketGateway;
        this.serviceProvider=serviceProvider;
        this.zkidrOnlineConfigVo=zkidrOnlineConfigVo;
    }

    public Boolean endListen()
    {
        startFlag=false;
        autoReconnect=false;
        this.close();
        return true;
    }

    public boolean start(boolean reconnect)
    {
        startFlag=false;
        while (shouldRun.get())
        {
            try
            {
                if(this.getReadyState().equals(READYSTATE.NOT_YET_CONNECTED))
                {
                    logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"状态为："+this.getReadyState()+"准备尝试连接");
                    if(!this.connectBlocking())
                    {
                        return false;
                    }
                    logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"正在发送启动消息:"+zkidrOnlineConfigVo.getStartMsg());
                    this.send(zkidrOnlineConfigVo.getStartMsg());
                    return true;
                }
                else if(this.getReadyState().equals(READYSTATE.CLOSED)||this.getReadyState().equals(READYSTATE.CLOSING))
                {
                    logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"状态为："+this.getReadyState()+"准备尝试重连");
                    if(!this.reconnectBlocking())
                    {
                        return false;
                    }
                    logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"正在发送启动消息:"+zkidrOnlineConfigVo.getStartMsg());
                    this.send(zkidrOnlineConfigVo.getStartMsg());
                    return true;
                }
            }
            catch (Exception e)
            {
                logger.error("连接ID:"+socketGatewayBase.getInstanceVo().getRunId()+"，设备ID:"+deviceId+"，自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败，错误原因："+e.getLocalizedMessage());
                try {
                    Thread.sleep(zkidrOnlineConfigVo.getReconnectDelay());
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                if(reconnect)
                {
                    logger.info("连接ID:"+socketGatewayBase.getInstanceVo().getRunId()+"，设备ID:"+deviceId+"，自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败，正在重连");
                }
                else
                {
                    break;
                }
            }
        }
        return false;
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"已经打开连接");
    }

    @Override
    public void onMessage(String message) {
        if(startFlag)
        {
            IDCardVo idCardVo=null;
            try
            {
                idCardVo= JSON.parseObject(message,IDCardVo.class);
                idCardVo.getCertificate().setReadID(deviceId);
                idCardVo.getCertificate().setReadTime(System.currentTimeMillis()+"");
            }
            catch (Exception e)
            {
                logger.error("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"解析数据发生异常:"+e.getLocalizedMessage());
            }

            if(idCardVo!=null&&serviceProvider!=null&&socketGatewayBase!=null)
            {
                SendService service = (SendService)serviceProvider.getByName(ServiceName.Send);
                SocketMessage socketMessage = socketGatewayBase.buildSocketMessage();
                socketMessage.setDeviceId(this.deviceId);
                socketMessage.setMsgKey("default");
                socketMessage.setData(JSON.toJSONString(idCardVo.getCertificate()).getBytes());
                socketMessage.getPropsMap().put("charset",  Charset.forName("GBK"));
                service.sendMessage(socketMessage);
                if(socketGatewayBase.getInstanceVo().getLogOpen())
                {
                    logger.error("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"收到数据:"+idCardVo.getCertificate());
                }
            }
        }
        else
        {
            ZKIDROnlineResponseVo zkidrOnlineResponseVo=null;
            try
            {
                zkidrOnlineResponseVo= JSON.parseObject(message,ZKIDROnlineResponseVo.class);
            }
            catch (Exception e)
            {
                logger.error("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"收到无法解析的数据:"+message);
            }
            if(zkidrOnlineResponseVo!=null&&SUCCESS_STR.equals(zkidrOnlineResponseVo.getData()))
            {
                logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"请求自动获取身份证信息成功");
                startFlag=true;
            }
            else
            {
                //this.close();
                this.start(true);
            }
        }

    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        if(startFlag&&remote)
        {
            logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"正在尝试重连");
            //this.close();
            this.start(true);
        }
        else
        {
            logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"正在关闭连接");
        }
    }

    @Override
    public void onError(Exception ex) {
        logger.error("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"发生异常:"+ex.getLocalizedMessage());
        if(autoReconnect)
        {
            try
            {
                Thread.sleep(reconnectDelay);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            logger.info("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"正在尝试重连");
            //this.close();
            this.start(true);
        }
        else
        {
            logger.warn("连接ID:"+runId+"，设备ID:"+deviceId+"，自动重连设置:"+autoReconnect+"未配置重连，连接关闭");
        }

    }
}
