/**
 * Copyright 2019 DH
 * All right reserved.
 * 项目名称: 大恒泰山系统
 * 创建日期:2021/12/20
 */
package org.ts.ddcs.tcp;

import com.alibaba.fastjson.JSONObject;
import org.ts.ddcs.log.LogHelper;
import org.ts.ddcs.net.SocketWorker;
import org.ts.ddcs.process.DataProcessHolder;
import org.ts.ddcs.tool.BytesHelp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.Callable;

/***
 * Date:2021/12/20
 * Title:文件所属模块（必须填写）
 * Description：对本文件的详细描述，原则上不能少于30字
 * @author dylan
 * @mender：（文件的修改者，文件创建者之外的人）
 * @version 1.0
 * Remark：认为有必要的其他信息
 */
public class TcpWorker implements Callable<Integer>, SocketWorker {
    private Socket socket;
    private String workerId;
    private String ip;
    private InputStream inputStream;
    private OutputStream outputStream;
    private boolean isShutDown = false;
    private String datagramAgreement = "1";

    public TcpWorker(String ip, Socket socket) {
        this.ip = ip;
        this.socket = socket;
        this.workerId = UUID.randomUUID().toString().replace("-", "").toLowerCase();
    }


    public boolean isConnected() {
        try {
            this.socket.sendUrgentData(0xFF);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    @Override
    public Integer call() throws Exception {
        SimpleDateFormat timeFormat2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        LogHelper.info(workerId + " get a tcp connect " + timeFormat2.format(new Date()));
        LogHelper.info(workerId + " ip " + ip);
        JSONObject info = new JSONObject();
        info.put("cmd", "8006");
        info.put("func", "connect");
        info.put("tm", timeFormat2.format(new Date()));
        info.put("ip", ip);
        info.put("text", "TCP连接已建立");
        LogHelper.info(info.toJSONString());
        DataProcessHolder.newInstance().dataProcess.mqttServer.send(info.toJSONString());
        inputStream = socket.getInputStream();
        outputStream = socket.getOutputStream();
        while (true) {
            try {
                if (isShutDown) {
                    break;
                }
                if (!isConnected()) {
                    break;
                }
                int available = inputStream.available();
                if (available <= 0) {
                    Thread.sleep(200);
                } else {
                    byte[] buff = new byte[available];
                    int count = inputStream.read(buff);
                    if (count > 0) {
                        info = new JSONObject();
                        info.put("cmd", "8006");
                        info.put("func", "read");
                        info.put("ip", ip);
                        info.put("tm", timeFormat2.format(new Date()));
                        if (datagramAgreement.equals("1")) {
                            String hexStr = BytesHelp.byte2HexStr(buff, 0, count);
                            info.put("text", hexStr);
                        } else if (datagramAgreement.equals("2")) {
                            String hexStr = new String(buff, 0, count);
                            info.put("text", hexStr);
                        }

                        LogHelper.info(info.toJSONString());
                        DataProcessHolder.newInstance().dataProcess.mqttServer.send(info.toJSONString());
                    }
                }

            } catch (IOException io) {
                LogHelper.error(io);
                info = new JSONObject();
                info.put("cmd", "8006");
                info.put("func", "close");
                info.put("ip", ip);
                info.put("tm", timeFormat2.format(new Date()));
                info.put("text", "RTU链接已断开");
                LogHelper.info(info.toJSONString());
                DataProcessHolder.newInstance().dataProcess.mqttServer.send(info.toJSONString());
                break;
            }
        }
        inputStream.close();
        outputStream.close();
        socket.close();
        DataProcessHolder.newInstance().dataProcess.removeTcpWorker(ip);
        return 0;
    }


    @Override
    public void close() {
        try {
            isShutDown = true;
            SimpleDateFormat timeFormat2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
            JSONObject info = new JSONObject();
            info.put("cmd", "8006");
            info.put("func", "close");
            info.put("ip", ip);
            info.put("tm", timeFormat2.format(new Date()));
            info.put("text", "链接已由服务器关闭");
            LogHelper.info(info.toJSONString());
            DataProcessHolder.newInstance().dataProcess.mqttServer.send(info.toJSONString());
        } catch (Exception e) {
            LogHelper.error(e);
        }
    }

    @Override
    public void put(String datagram, String datagramAgreement) {
        try {
            if (null != outputStream) {
                if (datagramAgreement.equals("1")) {
                    byte[] buff = BytesHelp.hexStr2Bytes(datagram);
                    if (null != buff && buff.length > 0) {
                        outputStream.write(buff);
                        outputStream.flush();
                    }
                } else if (datagramAgreement.equals("2")) {
                    byte[] buff = datagram.getBytes("utf-8");
                    if (null != buff && buff.length > 0) {
                        outputStream.write(buff);
                        outputStream.flush();
                    }
                }
            }
            SimpleDateFormat timeFormat2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
            JSONObject info = new JSONObject();
            info.put("cmd", "8006");
            info.put("func", "send");
            info.put("ip", ip);
            info.put("text", datagram);
            info.put("tm", timeFormat2.format(new Date()));
            LogHelper.info(info.toJSONString());
            DataProcessHolder.newInstance().dataProcess.mqttServer.send(info.toJSONString());
        } catch (Exception e) {
            LogHelper.error(e);
        }
    }
}
