package com.tsi.navi.service;

import android.app.Activity;
import android.content.Context;
import android.util.Log;

import androidx.annotation.UiThread;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.tsi.navi.dto.CpuNodeStatusDTO;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class TsiWebSocket {
    private static String TAG = TsiWebSocket.class.getSimpleName();

    private Context context;
    private Activity activity;
    private IWebSocket iWebSocket;
    private WebSocketClient naviClient;
    private String topics;
    private String prevTopics;
    private ObjectMapper mapper;

    public TsiWebSocket(@NotNull final Context context, @NotNull Activity activity, @NotNull IWebSocket iWebSocket) {
        this.context = context;
        this.activity = activity;
        this.iWebSocket = iWebSocket;
        this.topics = "";
        this.prevTopics = "";
        this.mapper = new ObjectMapper();
    }

    public boolean connect(String naviUrl) {

        Log.e(TAG, "try connect to: " + naviUrl);
        URI uri;
        try {
            uri = new URI(naviUrl);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return false;
        }

        this.naviClient = new WebSocketClient(uri) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                Log.i(TAG, "WebSocket: Opened");
                iWebSocket.onSocketOpen();
            }

            @UiThread
            @Override
            public void onMessage(String s) {
                //final String message = s;
                try {
                    CpuNodeStatusDTO status = mapper.readValue(s, CpuNodeStatusDTO.class);
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            iWebSocket.onSocketMessage(status);
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onClose(int i, String s, boolean b) {
                Log.e(TAG, "WebSocket: Closed: " + s);
                iWebSocket.onSocketClose();
            }

            @Override
            public void onError(Exception e) {
                Log.e(TAG, "WebSocket: Error: " + e.getMessage());
                iWebSocket.onSocketError(e.getMessage());
            }
        };
        this.naviClient.setReuseAddr(true);
        this.naviClient.connect();
        return true;
    }

    public boolean isOpen() {
        return this.naviClient.isOpen();
    }

    public void close() {
        if (isOpen()) {
            this.naviClient.close();
        }
    }

    public void sendGroup(String groupId) {
        if (this.naviClient.isOpen()) {
            this.naviClient.send("group:" + groupId);
        }
    }

    public void addTopic(String topic) {
        if (this.topics.equals("")) {
            this.topics = topic;
        }
        else {
            this.topics = this.topics + "," + topic;
        }
    }

    public void sendTopics() {
        if (!this.topics.equals("") && this.naviClient.isOpen()) {
            this.naviClient.send("topics:" + this.topics);
            this.prevTopics = this.topics;
            Log.e(TAG, "sendTopics topics:" + this.topics);
        }
        this.topics = "";
        if (!this.naviClient.isOpen()) {
            this.iWebSocket.onSocketClose();
        }
    }

    public void retrySendTopics() {
        if (!this.prevTopics.equals("") && this.naviClient.isOpen()) {
            this.naviClient.send("topics:" + this.prevTopics);
            Log.e(TAG, "retrySendTopics topics:" + this.prevTopics);
        }
        if (!this.naviClient.isOpen()) {
            this.iWebSocket.onSocketClose();
        }
    }

    /*public void addTopics(List<String> nodes) {
        String topics = "";
        for (String s: nodes) {
            topics = topics + s + ",";
        }
        if (this.naviClient.isOpen()) {
            this.naviClient.send("topics:" + topics);
        }
    }*/
}
