package com.ttstd.controller.signaling;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

public class WebSocketClient {

    private static final String TAG = "WebSocketClient";

    private final String serverUrl;
    private final String deviceId;
    private final Gson gson = new Gson();
    private final Handler mainHandler = new Handler(Looper.getMainLooper());
    private OkHttpClient client;
    private WebSocket webSocket;
    private SignalListener listener;

    public interface SignalListener {
        void onConnected();
        void onDisconnected();
        void onError(String error);
        void onMessage(SignalMessage message);
    }

    public WebSocketClient(String serverUrl, String deviceId) {
        this.serverUrl = serverUrl;
        this.deviceId = deviceId;
    }

    public void setListener(SignalListener listener) {
        this.listener = listener;
    }

    public void connect() {
        client = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(serverUrl).build();

        webSocket = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket ws, Response response) {
                Log.i(TAG, "WebSocket connected");
                registerDevice();
                mainHandler.post(() -> {
                    if (listener != null) listener.onConnected();
                });
            }

            @Override
            public void onMessage(WebSocket ws, String text) {
                Log.d(TAG, "Received: " + text);
                try {
                    SignalMessage message = gson.fromJson(text, SignalMessage.class);
                    mainHandler.post(() -> {
                        if (listener != null) listener.onMessage(message);
                    });
                } catch (Exception e) {
                    Log.e(TAG, "Error parsing message", e);
                }
            }

            @Override
            public void onClosed(WebSocket ws, int code, String reason) {
                Log.i(TAG, "WebSocket closed: " + reason);
                mainHandler.post(() -> {
                    if (listener != null) listener.onDisconnected();
                });
            }

            @Override
            public void onFailure(WebSocket ws, Throwable t, Response response) {
                Log.e(TAG, "WebSocket error: " + t.getMessage(), t);
                mainHandler.post(() -> {
                    if (listener != null) listener.onError(t.getMessage());
                });
            }
        });
    }

    public void sendMessage(SignalMessage message) {
        if (webSocket != null) {
            String json = gson.toJson(message);
            Log.d(TAG, "Sending: " + json);
            webSocket.send(json);
        }
    }

    public void disconnect() {
        if (webSocket != null) {
            webSocket.close(1000, "Disconnecting");
        }
        if (client != null) {
            client.dispatcher().executorService().shutdown();
        }
    }

    private void registerDevice() {
        SignalMessage registerMsg = new SignalMessage();
        registerMsg.setType("REGISTER");
        registerMsg.setFromDeviceId(deviceId);
        registerMsg.setDeviceType("CONTROLLER");
        sendMessage(registerMsg);
    }

    public boolean isConnected() {
        return webSocket != null;
    }
}
