package com.nbusy.sdk.titan.neptulon;

import com.google.gson.Gson;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.ws.WebSocket;
import okhttp3.ws.WebSocketCall;
import okhttp3.ws.WebSocketListener;
import okio.Buffer;

/**
 * Neptulon connection implementation: https://github.com/neptulon/neptulon
 */
public class ConnImpl implements /*Conn,*/ WebSocketListener {
    private static final Logger logger = Logger.getLogger(ConnImpl.class.getSimpleName());
    private final Gson gson = new Gson();
    private final OkHttpClient client;
    private final Request request;
    private final WebSocketCall wsCall;
    private WebSocket ws;

    /**
     * Initializes a new connection with given server URL.
     */
    public ConnImpl(String url) {
        client = new OkHttpClient.Builder()
                .connectTimeout(45, TimeUnit.SECONDS)
                .writeTimeout(300, TimeUnit.SECONDS)
                .readTimeout(300, TimeUnit.SECONDS)
                .build();

        request = new Request.Builder()
                .url(url)
                .build();

        wsCall = WebSocketCall.create(client, request);
    }

    /**
     * Initializes a new connection with default server URL: "ws://10.0.2.2:3000" ("ws://127.0.0.1:3000" on Android emulator host machine).
     */
    public ConnImpl() {
        this("ws://10.0.2.2:3010");
    }

    /*
     * == Conn implementation.
     */

    //    @Override
    public void useTLS(byte[] ca, byte[] clientCert, byte[] clientCertKey) {
        // todo: https://github.com/square/okhttp/wiki/HTTPS
    }

    //    @Override
    public void connect() {
        // enqueue this listener implementation to initiate the WebSocket connection
        wsCall.enqueue(this);
    }

    //    @Override
    public void send() throws IOException {
        ws.sendMessage(RequestBody.create(WebSocket.TEXT, "{\"ID\": \"123\", \"Method\": \"test2\"}"));
    }

    //    @Override
    public void close() throws IOException {
        ws.close(0, "");
    }

    /*
     * WebSocketListener implementation.
     */

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        ws = webSocket;
        logger.info("WebSocket connected.");
    }

    @Override
    public void onFailure(IOException e, Response response) {
        logger.warning("WebSocket connection closed with error: " + e.getMessage());
    }

    @Override
    public void onMessage(ResponseBody message) throws IOException {
        Message msg = gson.fromJson(message.string(), Message.class);
        if (!msg.method.isEmpty()) {
            // handle request message
            // todo: return new ReqCtx(....).Next();
            return;
        }

        // handle response message
        // todo: return resHandler(ResCtx);
    }

    @Override
    public void onPong(Buffer payload) {
    }

    @Override
    public void onClose(int code, String reason) {
        logger.info("WebSocket closed.");
    }
}

@@ -538,17 +538,13 @@
 nts 
-/*
 Conn,
-*/
  Web
@@ -1418,18 +1418,42 @@
 .2:3000%22
+%0A     * which connects to
  
-(
 %22ws://12
@@ -1498,17 +1498,16 @@
  machine
-)
 .%0A     *
@@ -1593,17 +1593,23 @@
   * 
-==
+########
  Conn 
-i
+I
 mple
@@ -1609,33 +1609,41 @@
 n Implementation
-.
+ ########
 %0A     */%0A%0A    //
@@ -1636,22 +1636,16 @@
     */%0A%0A
-    //
     @Ove
@@ -1788,33 +1788,249 @@
 i/HTTPS%0A    
-%7D%0A%0A
+    // * pin and use a single trusted custom server cert%0A   
     
+ 
 //
+ * limit ciphers and TLS version%0A    %7D%0A%0A    @Override%0A    public void setDeadline(int seconds) %7B%0A%0A    %7D%0A%0A    @Override%0A    public void middleware() %7B%0A%0A    %7D%0A%0A
     @Overrid
@@ -2189,230 +2189,494 @@
     
-//    @Override%0A    public void send() throws IOException %7B%0A        ws.sendMessage(RequestBody.create(WebSocket.TEXT, %22%7B%5C%22ID%5C%22: %5C%22123%5C%22, %5C%22Method%5C%22: %5C%22test2%5C%22%7D%22));%0A    %7D%0A%0A    //    @Override%0A    public void close() throws 
+@Override%0A    public void remoteAddr() %7B%0A%0A    %7D%0A%0A    @Override%0A    public void sendRequest(int resHandler) %7B%0A        try %7B%0A            ws.sendMessage(RequestBody.create(WebSocket.TEXT, %22%7B%5C%22ID%5C%22: %5C%22123%5C%22, %5C%22Method%5C%22: %5C%22test2%5C%22%7D%22));%0A        %7D catch (IOException e) %7B%0A            e.printStackTrace();%0A        %7D%0A    %7D%0A%0A    @Override%0A    public void sendRequestArr(int resHandler) %7B%0A%0A    %7D%0A%0A    @Override%0A    public void close() %7B%0A        try %7B%0A            ws.close(0, %22%22);%0A        %7D catch (
 IOEx
@@ -2674,32 +2674,35 @@
 tch (IOException
+ e)
  %7B%0A        ws.cl
@@ -2696,32 +2696,50 @@
         
+ 
-ws.close(0, %22%22);
+   e.printStackTrace();%0A        %7D
 %0A    %7D%0A%0A
@@ -2751,16 +2751,25 @@
 *%0A     *
+ ########
  WebSock
@@ -2771,33 +2771,33 @@
 bSocketListener 
-i
+I
 mplementation.%0A 
@@ -2793,17 +2793,25 @@
 entation
-.
+ ########
 %0A     */
@@ -3584,24 +3584,73 @@
  payload) %7B%0A
+        logger.info(%22WebSocket pong received.%22);%0A
     %7D%0A%0A    @

improve Conn impl