package com.sambath.kunkhmer.remote.service;

import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;

import android.util.Log;

import com.sambath.kunkhmer.config.Config;
import com.sambath.kunkhmer.util.BaseObservable;

import org.json.JSONObject;

import java.net.URI;
import java.net.URISyntaxException;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

public class SocketService extends BaseObservable<EventListener> {
    private static final String TAG = "Socket";
    private static final String SOCKET_1 = Config.SOCKET_1;
//    private static final String SOCKET_2 = Config.SOCKET_2;
//    private static final String SOCKET_3 = Config.SOCKET_3;
//    private static final String SOCKET_4 = Config.SOCKET_4;
    private static final String EVENT_CONNECT = Socket.EVENT_CONNECT;
    private static final String EVENT_CONNECT_ERROR = Socket.EVENT_CONNECT_ERROR;
    private static final String EVENT_DISCONNECT = Socket.EVENT_DISCONNECT;
    private static final String EVENT_UPDATE_CHANNEL_INFO = "client-update-channel-info";
    private static final String EVENT_DEFINED_RESULT_AND_CHANNEL = "client-defind-result-and-new-channel";
    private static final String EVENT_UPDATE_USER_INFO = "client-update-user-info";
    private static final String EVENT_UPDATE_BETTING_AMOUNT = "client-update-betting-amount";
    private static final String EVENT_UPDATE_PAYOUT = "client-update-payout";
    private static final String EVENT_REVERSE_RESULT = "client-reserves-result";
    private static final String EVENT_RESET_AMOUNT = "client-reset-amount";
    private Socket mSocket;

    public void startListening(String token, int channelType) throws URISyntaxException {
        IO.Options options = IO.Options.builder()
                .setExtraHeaders(singletonMap("authorization", singletonList(token)))
                .build();
        Log.d("Socket", "startListening mSocket"+ channelType);
        mSocket = IO.socket(URI.create(SOCKET_1), options);
        mSocket.on(EVENT_CONNECT, connectListener);
        mSocket.on(EVENT_UPDATE_CHANNEL_INFO, updateChannelInfo);
        mSocket.on(EVENT_DEFINED_RESULT_AND_CHANNEL, definedResultAndChannel);
        mSocket.on(EVENT_UPDATE_USER_INFO, updateUserInfo);
        mSocket.on(EVENT_UPDATE_BETTING_AMOUNT, updateBettingAmount);
        mSocket.on(EVENT_UPDATE_PAYOUT, updatePayout);
        mSocket.on(EVENT_REVERSE_RESULT, reverseResult);
        mSocket.on(EVENT_RESET_AMOUNT, resetAmount);
        mSocket.on(EVENT_DISCONNECT, disconnectListener);
        mSocket.on(EVENT_CONNECT_ERROR, connectionErrorListener);
        mSocket.connect();
    }

    private Emitter.Listener updateChannelInfo = args -> {
        Log.d("Socket", "updateChannelInfo s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onUpdateChannelInfo(rawMessage);
    };
    private Emitter.Listener definedResultAndChannel = args -> {
        Log.d("Socket", "definedResultAndChannel s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onDefinedResultAndChannel(rawMessage);
    };
    private Emitter.Listener updateUserInfo = args -> {
        Log.d("Socket", "updateUserInfo s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onUpdateUserInfo(rawMessage);
    };
    private Emitter.Listener updateBettingAmount = args -> {
        Log.d("Socket", "updateBettingAmount s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onUpdateBettingAmount(rawMessage);
    };
    private Emitter.Listener updatePayout = args -> {
        Log.d("Socket", "updatePayout s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onUpdatePayout(rawMessage);
    };
    private Emitter.Listener reverseResult = args -> {
        Log.d("Socket", "reverseResult s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onReverseRseult(rawMessage);
    };
    private Emitter.Listener resetAmount = args -> {
        Log.d("Socket", "resetAmount s...fghfhgfhgfhfghgf");
        final String rawMessage = args[0].toString();
        for (EventListener listener : getListeners())
            listener.onResetAmount(rawMessage);
    };
    private Emitter.Listener connectListener = args -> {
        Log.d("Socket", "onConnect s...fghfhgfhgfhfghgf");
        for (EventListener listener : getListeners())
            listener.onConnect();
    };

    public void stopListening() {
        if (mSocket != null)
            mSocket.disconnect();
    }

    public void switchChannel(String token, int channelType) throws URISyntaxException {
        if (mSocket != null)
            mSocket.disconnect();
        startListening(token, channelType);
    }

    public void startEmitCfCreateBetting(JSONObject joinObject) {
        mSocket.emit("player-betting", joinObject);
    }

    private Emitter.Listener connectionErrorListener = args -> {
//        Log.d(TAG,"onConnectionError s..."+args[0].toString());
        for (EventListener listener : getListeners())
            listener.onConnectionError();
    };

    private Emitter.Listener disconnectListener = args -> {
//        Log.d(TAG,"onDisconnect s..."+args[0].toString());
        mSocket.off();
        for (EventListener listener : getListeners()) {
            listener.onDisconnect();
        }
    };
}
