package com.khmer9.lotto.remote.service;

import android.util.Log;

import com.github.nkzawa.emitter.Emitter;
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
import com.khmer9.lotto.remote.SocketMessageDataModel;
import com.khmer9.lotto.util.BaseObservable;

import org.json.JSONException;
import org.json.JSONObject;

import java.net.URISyntaxException;

import com.khmer9.lotto.config.Config;

public class SocketService extends BaseObservable<EventListener> {

    private static final String TAG = "Socket";

    private static final String SOCKET_URL = Config.SOCKET_URL;
    private static final String EVENT_CONNECT = Socket.EVENT_CONNECT;
    private static final String EVENT_RECONNECT = Socket.EVENT_RECONNECT;
    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_CONNECT_TIMEOUT = Socket.EVENT_CONNECT_TIMEOUT;
    private static final String EVENT_NEW_LOTTO_MESSAGE = "start-count-down-loto";
    private static final String EVENT_NEW_CREATE_BETTING_MESSAGE = "created-betting-by-user";


    private Socket socket ;
    private JSONObject joinBettingObject ;

    private Emitter.Listener connectListener = args -> {
        //Log.d(TAG,"onConnect s...");
        socket.emit("join", joinBettingObject);
        for(EventListener listener: getListeners())
            listener.onConnect();
    };

    public void startEmitCreateBetting(JSONObject joinObject){
        socket.emit("betting-loto",joinObject);
    }

    private Emitter.Listener reconnectListener = args -> {
        //Log.d(TAG,"onReconnect s...");
        for(EventListener listener: getListeners())
            listener.onReconnect();
    };

    private Emitter.Listener connectTimeoutListener = args -> {
        //Log.d(TAG,"onConnectTimeout s...");
        for(EventListener listener: getListeners())
            listener.onReconnectionTimeout();
    };

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

    private Emitter.Listener disconnectListener = args -> {
        //Log.d(TAG,"onDisconnect s...");
        socket.off();
        for(EventListener listener: getListeners()){
            listener.onDisconnect();

        }

    };

    //    {"countDown":[12,34,11,69],
//        "type":"random",
//        "object":{"objRandom":
//                            {"total":806,
//                            "numbers":[12,34,11,69,59,74,30,9,38,65,52,29,8,14,68,55,31,10,60,78]
//                            }
//                }
//    }
    // {"countDown":129,"type":"count"}

    private Emitter.Listener newOtherCreatedBettingMessageListener = args -> {
        final String rawMessage = args[0].toString() ;
        //Log.d(TAG,"onCreateMessage: "+rawMessage);
        try {
            JSONObject rawMessageObject = new JSONObject(rawMessage);
            //String userID = rawMessageObject.getString("user_id");
            for (EventListener listener : getListeners())
                listener.onNewCreatedBettingMessage(rawMessageObject);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    };

    private Emitter.Listener newLottoMessageListener = args -> {
        final String rawMessage = args[0].toString() ;
        //Log.d(TAG,"onNewLottoMessage: "+rawMessage);
        try {
            SocketMessageDataModel lottoMessage;
            JSONObject rawMessageObject = new JSONObject(rawMessage);
            final String type = rawMessageObject.getString("type");
            if (type.equals("count")){
                lottoMessage = new SocketMessageDataModel(type,rawMessageObject.getInt("countDown"),null, null,false, null, null);

            }else {//type =random
                JSONObject objectTotal = rawMessageObject.getJSONObject("object");
                int totalVale = objectTotal.getInt("objRandom");
                JSONObject objectBonus = objectTotal.getJSONObject("bornus");
                boolean isBonus = objectBonus.getBoolean("bornusStatus");
                int bonusNumer = objectBonus.getInt("bornus");
                int bonusValue = objectBonus.getInt("paymentBornus");
                lottoMessage = new SocketMessageDataModel(type,null,rawMessageObject.getJSONArray("countDown"), totalVale, isBonus, bonusNumer, bonusValue);
            }
            // final long timeStamp = System.currentTimeMillis();
            for (EventListener listener : getListeners())
                listener.onNewLottoMessage(lottoMessage);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    };

    public void startListening(JSONObject joinBettingObject) throws URISyntaxException {
        this.joinBettingObject = joinBettingObject;

        if(socket==null)
            socket = IO.socket(SOCKET_URL) ;

        socket.on(EVENT_CONNECT, connectListener);
        socket.on(EVENT_CONNECT_TIMEOUT,connectTimeoutListener);
        socket.on(EVENT_DISCONNECT, disconnectListener);
        socket.on(EVENT_NEW_LOTTO_MESSAGE, newLottoMessageListener);
        socket.on(EVENT_NEW_CREATE_BETTING_MESSAGE, newOtherCreatedBettingMessageListener);
        socket.on(EVENT_RECONNECT,reconnectListener);
        socket.on(EVENT_CONNECT_ERROR,connectionErrorListener);

        socket.connect();
    }

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

//    public Single<ChatMessage> sendMessage(ChatMessage chatMessage) {
//        return Single.create(singleEmitter -> {
//            if (socket == null)
//                singleEmitter.onError(new NullSocketException());
//            socket.emit(EVENT_NEW_MESSAGE, chatMessage.getMessageText());
//            chatMessage.setSent(true);
//            singleEmitter.onSuccess(chatMessage);
//        });
//    }
}
