package edu.whs.spin2018.baoapp.views.lobby;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

import edu.whs.spin2018.baoapp.R;
import edu.whs.spin2018.baoapp.model.Benutzer;
import edu.whs.spin2018.baoapp.model.benutzerinfo.SharedPrefHelfer;
import edu.whs.spin2018.baoapp.presenter.LobbyPresenter;
import edu.whs.spin2018.baoapp.service.BaoService;
import edu.whs.spin2018.baoapp.service.Konstanten;
import edu.whs.spin2018.baoapp.model.remote.lobby.LobbyServiceInteractor;
import edu.whs.spin2018.baoapp.model.remote.lobby.LobbyRemoteDataSource;
import edu.whs.spin2018.baoapp.utilities.ViewUtils;
import edu.whs.spin2018.baoapp.views.OnlineActivity;
import edu.whs.spin2018.baoapp.views.menues.SpieleinstellungenActivity;

/**
 * LobbyActivity, in der alle Benutzer, die sich auf dem Server in dem dazugehörigen Raum befinden,
 * angezeigt werden.
 */
public class LobbyActivity extends OnlineActivity implements LobbyContract.View, HerausforderungsDialog.OnActionHappenedListener {

    private static final String TAG = "LobbyActivityTAG";
    /**
     * Adapter um mit der RecyclerList zu kommunizieren.
     */
    private BenutzerAdapter mBenutzerAdapter;

    /**
     * True, wenn ein Dialog fuer eine Herausforderung angezeigt wird.
     */
    private HerausforderungsDialog mAktuellerDialog;

    /**
     * Dienen zum Anzeigen des Ladestatuses der Benutzer in der Lobby.
     */
    private ProgressBar mLadeAnzeige;
    private TextView mLadeStatus;

    /**
     * Liste, in der die Benutzer in der Lobby angezeigt werden.
     */
    private RecyclerView mBenutzerRecyclerView;

    /**
     * BaoPresenter zum kommunizieren zwischen View und Model
     */
    private LobbyContract.Presenter mLobbyPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(edu.whs.spin2018.baoapp.R.layout.activity_lobby);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    @Override
    public void zeigeNeuenBenutzerInListe(int pos) {
        runOnUiThread(() -> mBenutzerAdapter.notifyItemChanged(pos));

    }

    @Override
    public void entferneBenutzerAusAnzeigeliste(int pos, int anzahl) {
        runOnUiThread(() -> {
            mBenutzerAdapter.notifyItemRemoved(pos);
            mBenutzerAdapter.notifyItemRangeChanged(pos, anzahl);
        });
    }

    @Override
    public void zeigeLobbyIstLeer() {
        runOnUiThread(() -> {
            mLadeStatus.setVisibility(View.VISIBLE);
            mLadeStatus.setText(getString(R.string.lobby_tv_ladestatus_leer));
            mLadeAnzeige.setVisibility(View.INVISIBLE);
        });
    }

    @Override
    public void zeigeBenutzerWerdenGeladen() {
        runOnUiThread(() -> {
            mLadeStatus.setText(R.string.lobby_tv_ladestatus_label);
            mLadeStatus.setVisibility(View.VISIBLE);
            mLadeAnzeige.setVisibility(View.VISIBLE);
        });
    }

    @Override
    public void versteckeLadeAnzeige() {
        runOnUiThread(() -> {
            mLadeAnzeige.setVisibility(View.INVISIBLE);
            mLadeStatus.setVisibility(View.INVISIBLE);
            mBenutzerRecyclerView.setVisibility(View.VISIBLE);
        });

    }

    @Override
    public void zeigeEingehendeHerausforderung(Benutzer absender) {

        /*
         * Bei eingehender Herausforderung einen Dialog erstellen und diesem die Daten des
         * Herausforderers geben.
         */
        if (mAktuellerDialog == null) {
            mAktuellerDialog = HerausforderungEingehendDialog
                    .newInstance(absender.gibBenutzernamen(), absender.gibUUID());
            mAktuellerDialog.show(getSupportFragmentManager(), "herausforderungEingehend");
            mAktuellerDialog.setzeOnActionHappenedListener(this);
        }

    }

    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        Log.d(TAG, "onSaveInstanceState: saved State");
    }

    @Override
    public void zeigeAusgehendeHerausforderung(Benutzer empfaenger) {
        if (mAktuellerDialog == null) {
            mAktuellerDialog = HerausforderungAusgehendDialog
                    .newInstance(empfaenger.gibBenutzernamen(), empfaenger.gibUUID());
            mAktuellerDialog.show(getSupportFragmentManager(), "herausforderungAusgehend");
            mAktuellerDialog.setzeOnActionHappenedListener(this);
        }
    }

    @Override
    public void zeigeHerausforderungBeendet() {
        if (mAktuellerDialog != null) {
            runOnUiThread(() -> mAktuellerDialog.zeigeHerausforderungBeendet());
        }
    }

    @Override
    public void zeigeHerausforderungAngenommen() {
        if (mAktuellerDialog != null) {
            runOnUiThread(() -> mAktuellerDialog.zeigeHerausforderungAngenommen());
        }
    }

    @Override
    public void leereListe(int anzahl) {
        runOnUiThread(() -> mBenutzerAdapter.notifyItemRangeRemoved(0, anzahl));
    }

    @Override
    public void zeigeErhaltendeBenutzer() {
        runOnUiThread(() -> mBenutzerAdapter.notifyDataSetChanged());
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: " + mAktuellerDialog);
        mLobbyPresenter.stop();
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        new LobbyPresenter(this, new SharedPrefHelfer(this));
    }

    @Override
    public void initView() {
        //View Komponenten initialisieren
        mLadeAnzeige = findViewById(R.id.lobby_pb_ladeindikator);
        mLadeStatus = findViewById(R.id.lobby_tv_ladestatus);
        TextView mBanner = findViewById(R.id.lobby_heading);

        ViewUtils.setzeSchatten(mBanner);

        /*
        RecyclerView in der die Benutzer angezeigt werden.
        */
        mBenutzerRecyclerView = findViewById(R.id.lobby_rv_benutzerliste);

        //Benutzer werden in einer vertikalen Listet angezeigt
        mBenutzerRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        //Seperator zwischen den Einträgen
        mBenutzerRecyclerView.addItemDecoration(new DividerItemDecoration(this,
                LinearLayoutManager.VERTICAL));

        mBenutzerAdapter = new BenutzerAdapter(mLobbyPresenter);
        mBenutzerRecyclerView.setAdapter(mBenutzerAdapter);


        ItemClickSupport.addTo(mBenutzerRecyclerView)
                .setOnItemClickListener((recyclerView, position, v) -> mLobbyPresenter.sendeHerausforderung(position));
    }

    @Override
    public void setzePresenter(LobbyContract.Presenter presenter) {
        this.mLobbyPresenter = presenter;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: Lobby destroyed");
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mAktuellerDialog != null) {
            mAktuellerDialog.dismissAllowingStateLoss();
            mAktuellerDialog = null;
        }
        Log.d(TAG, "onPause: Lobby paused");
    }

    /*---------------------------------------------------------------------------------------------
                                               OnlineActivity Methoden
                 --------------------------------------------------------------------------------------------*/
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i("BaoService", "Service bound");
        BaoService baoServiceInterface = ((BaoService.LocalBinder) service).getService();
        LobbyRemoteDataSource serviceInteractor = new LobbyServiceInteractor(baoServiceInterface);
        mLobbyPresenter.setzeServiceInteractor(serviceInteractor);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i("BaoService", "Service unbound");
    }

    /*---------------------------------------------------------------------------------------------
                                    OnActionHappened Methoden
     --------------------------------------------------------------------------------------------*/
    @Override
    public void onDialogBeendet() {
        mAktuellerDialog = null;
        mLobbyPresenter.beendeDialog();
    }

    @Override
    public void onDialogCanceled(String gegnerUUID) {
        mLobbyPresenter.lehneHerausforderungAb(gegnerUUID);
        mAktuellerDialog = null;
    }

    @Override
    public void onHerausforderungAblehnenClicked(String gegnerUUID) {
        if (mAktuellerDialog != null) {
            mLobbyPresenter.lehneHerausforderungAb(gegnerUUID);
        }
        mAktuellerDialog = null;
    }

    @Override
    public void onHerausforderungAngenommenClicked(String gegnerUUID) {
        if (mAktuellerDialog != null) {
            mLobbyPresenter.nimmHerausforderungAn(gegnerUUID);

        }
    }

    @Override
    public void onHerausforderungAbbrechenClicked(String gegnerUUID) {
        if (mAktuellerDialog != null) {
            //Ablehnen Event an den Presenter weitergeben
            mLobbyPresenter.lehneHerausforderungAb(gegnerUUID);
            mAktuellerDialog = null;
        }
    }

    @Override
    public void starteSpieleinstellungen(Benutzer gegner, String raum) {
        Log.d(TAG, "starteSpieleinstellungen: " + mAktuellerDialog);

        Intent ladeSpieleinstellungen = new Intent(this, SpieleinstellungenActivity.class);
        ladeSpieleinstellungen.putExtra(Konstanten.EXTRA_GEGNER_NAME,
                gegner.gibBenutzernamen());
        ladeSpieleinstellungen.putExtra(Konstanten.EXTRA_GEGNER_UUID,
                gegner.gibUUID());
        ladeSpieleinstellungen.putExtra(Konstanten.EXTRA_RAUM, raum);

        startActivity(ladeSpieleinstellungen);
    }
}
