package edu.whs.spin2018.baoapp.model.remote.lobby;

import android.support.annotation.NonNull;
import android.util.Log;

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

import java.util.List;

import edu.whs.spin2018.baoapp.model.Benutzer;
import edu.whs.spin2018.baoapp.model.Nachricht;
import edu.whs.spin2018.baoapp.service.BaoService;
import edu.whs.spin2018.baoapp.model.remote.ServiceInteractor;
import edu.whs.spin2018.baoapp.service.SocketEvents;
import edu.whs.spin2018.baoapp.utilities.JSONUtils;
import io.socket.emitter.Emitter;


public class LobbyServiceInteractor extends ServiceInteractor implements LobbyRemoteDataSource {

    private static final String TAG = "LobbyInteractorTAG";

    /**
     * Listener an den die erhaltenden Events weitergeleitet werden.
     */
    private LobbyEventListener listener;

    /**
     * Listener der benachrichtigt wird, wenn ein Benutzer den Raum verlaesst.
     */
    private final Emitter.Listener OnBenutzerVerlaesstRaumListener = args -> {
        Benutzer benutzer = JSONUtils.gibBenutzerVonJSONObjekt((JSONObject) args[0]);
        Log.d(TAG, "Benutzer verlaesst Raum: " + benutzer);
        onBenutzerVerlaesstRaumErhalten(benutzer);
    };

    /**
     * Listener fuer das Erhalten der Benutzerliste der Lobby.
     */
    private final Emitter.Listener OnBenutzerImRaumListener = (args) -> {
        Log.d(TAG, "call: OnBenutzerListeErhalten");
        onBenutzerlisteErhalten(JSONUtils
                .gibBenutzerlisteVonJSONObjekt(args[0]));
    };

    /**
     * Raum, in dem sich der Spieler gerade befindet
     */
    private String aktuellerRaum = "";

    /**
     * Listener fuer das Beitreten von Benutzern in den aktuellen Raum
     */
    private final Emitter.Listener OnBenutzerTrittRaumBeiListener = args -> {
        Benutzer benutzer = JSONUtils.gibBenutzerVonJSONObjekt((JSONObject) args[0]);
        Log.d(TAG, "Benutzer tritt Raum bei: " + benutzer);
        onBenutzerTrittRaumBeiErhalten(benutzer);
    };

    public LobbyServiceInteractor(@NonNull BaoService serviceInterface) {
        super(serviceInterface);
        registriereBenoetigteListener();
    }

    @Override
    public void registriereBenoetigteListener() {
        registriereBenutzerTrittRaumBeiListener(OnBenutzerTrittRaumBeiListener);
        registriereBenutzerVerlaesstRaumListener(OnBenutzerVerlaesstRaumListener);
        registriereBenutzerListeErhaltenListener(OnBenutzerImRaumListener);
    }

    @Override
    public void entferneRegistrierteListener() {
        entferneListener(SocketEvents.BENUTZER_TRITT_RAUM_BEI, OnBenutzerTrittRaumBeiListener);
        entferneListener(SocketEvents.BENUTZER_VERLAESST_RAUM, OnBenutzerVerlaesstRaumListener);
        entferneListener(SocketEvents.BENUTZERLISTE_ERHALTEN, OnBenutzerImRaumListener);
    }

    @Override
    public void onNeueNachricht(Object... args) {
        JSONObject data = (JSONObject) args[0];
        String typ = "";
        Log.d(TAG, "onNeueNachricht: " + data);

        try {
            typ = data.getString("type");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        Benutzer benutzer = null;
        switch (typ) {

            case Nachricht.TYP_HERAUSFORDERUNG_NEU:
                try {
                    benutzer = Benutzer.vonString(data.getString("inhalt"));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                listener.onHerausforderungErhalten(benutzer);
                break;

            //Nachricht, dass die Herausforderung vom Gegner angenommen wurde
            case Nachricht.TYP_HERAUSFORDERUNG_ANGENOMMEN:
                listener.onHerausforderungAngenommenErhalten();
                break;

            //Nachricht, dass die Herausforderung vom Gegner beendet wurde
            case Nachricht.TYP_HERAUSFORDERUNG_BEENDET:
                listener.onHerausforderungBeendetErhalten();
                break;
        }
    }

    @Override
    public void sendeHerausforderung(String empfaengerUUID, Benutzer ich) {
        sendeNachricht(ich.toString(),
                Nachricht.TYP_HERAUSFORDERUNG_NEU, empfaengerUUID);
    }

    @Override
    public void lehneHerausforderungAb(String absenderUUID) {
        sendeNachricht("", Nachricht.TYP_HERAUSFORDERUNG_BEENDET, absenderUUID);
    }

    @Override
    public void nimmHerausforderungAn(String gegnerUUID) {
        sendeNachricht(null, Nachricht.TYP_HERAUSFORDERUNG_ANGENOMMEN, gegnerUUID);
    }

    @Override
    public void verlasseLobby() {
        raumVerlassen("Lobby");
        aktuellerRaum = "";
    }

    @Override
    public void verlasseAktuellenRaum() {
        raumVerlassen(aktuellerRaum);
        Log.d(TAG, "verlasseAktuellenRaum: " + aktuellerRaum + ";");
        aktuellerRaum = "";
    }

    @Override
    public void geheInLobby() {
        if (!aktuellerRaum.equals("Lobby")) {
            raumBetreten("Lobby");
            aktuellerRaum = "Lobby";
        }
    }

    @Override
    public void geheInNeuenRaum(String neuerRaum) {
        aktuellerRaum = neuerRaum;
        raumBetreten(neuerRaum);
    }


    @Override
    public void ladeBenutzerInLobby() {
        zeigeBenutzerImRaum("Lobby");
    }

    @Override
    public void setzeListener(LobbyEventListener listener) {
        this.listener = listener;
    }

    @Override
    public void onHerausforderungErhalten(Benutzer absender) {
        listener.onHerausforderungErhalten(absender);
    }

    @Override
    public void onHerausforderungBeendetErhalten() {
        listener.onHerausforderungBeendetErhalten();
    }

    @Override
    public void onHerausforderungAngenommenErhalten() {
        listener.onHerausforderungAngenommenErhalten();
    }

    @Override
    public void onBenutzerVerlaesstRaumErhalten(Benutzer benutzer) {
        listener.onBenutzerVerlaesstRaumErhalten(benutzer);
    }

    @Override
    public void onBenutzerTrittRaumBeiErhalten(Benutzer benutzer) {
        if (aktuellerRaum.equals("Lobby")) {
            listener.onBenutzerTrittRaumBeiErhalten(benutzer);
        }
    }

    @Override
    public void onBenutzerlisteErhalten(List<Benutzer> benutzerliste) {
        listener.onBenutzerlisteErhalten(benutzerliste);
    }



}
