package com.wecise.odb;

import com.google.gson.Gson;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.HashMap;

public class Connector implements Runnable {
    private Socket socket;
    private boolean alive;
    private boolean closed;

    public Connector(Socket socket) {
        this.socket = socket;
        if (socket != null && !socket.isClosed()) {
            this.alive = true;
            this.closed = false;
        }
    }

//    public Socket getSocket() {
//        return this.socket;
//    }

    public boolean isAlive() {
        return this.alive;
    }

    public void close() {
        try {
            if (!this.socket.isClosed()) {
                if (!this.socket.isInputShutdown()) {
                    this.socket.shutdownInput();
                }
                if (!this.socket.isOutputShutdown()) {
                    this.socket.shutdownOutput();
                }
                this.socket.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.closed = true;
    }

    public boolean isClosed() {
        return this.closed;
    }

    public synchronized Message request(String uri, String body) {
        HashMap<String, String> meta = new HashMap<>();
        meta.put("X-Accept-Body-Codec", "106");
        Message sendmsg = new Message("", 1, uri, meta, 'j', body);
        Message recvmsg = null;
        try {
            OutputStream outputStream = socket.getOutputStream(); // 获取一个输出流，向服务端发送信息
            outputStream.write(sendmsg.encode());
            outputStream.flush();
//            PrintWriter printWriter = new PrintWriter(outputStream); // 将输出流包装成打印流
//            printWriter.print(s);
//            printWriter.flush();

            InputStream inputStream = socket.getInputStream(); // 获取一个输入流，接收服务端的信息
            recvmsg = new Message();
            recvmsg.decode(inputStream);
//            System.out.println(recvmsg.getBody());
        } catch (Exception e) {
            // Output or receive message error do nothing.
        }
        // 关闭相对应的资源，我们这里不需要

        return recvmsg;
    }

    @Override
    public void run() { // For heartbeat
        int heartbeatSecond = 3;
        while (!closed) {
            try {
                Message m = request("/heartbeat?hb_" + heartbeatSecond, "");
                if (m == null) {
                    reconnect();
                }
                Thread.sleep(heartbeatSecond * 1000);
            } catch (ConnectException e) {
                // Reconnect exception do nothing.
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void reconnect() throws IOException {
        this.alive = false;
        this.socket.close();
        SocketAddress address = this.socket.getRemoteSocketAddress();
        Socket newSocket = new Socket();
        newSocket.connect(address);
        this.socket = newSocket;
        this.alive = true;
    }
}
