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

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import edu.whs.spin2018.baoapp.presenter.BaoSpielPresenter;
import edu.whs.spin2018.baoapp.R;
import edu.whs.spin2018.baoapp.service.Konstanten;
import edu.whs.spin2018.baoapp.utilities.ViewUtils;
import edu.whs.spin2018.baoapp.views.spiel.BaoSpielActivity;

/**
 * Diese Klasse ermöglicht die Einigung der Spieleinstellungen zweier Spieler für den lokalen Modus.
 * Wenn zwei Spieler über ein Gerät gegeneinander spielen möchten, können hier die gewünschten
 * Spieleinstellungen festgelegt werden.
 */
public class LokaleSpieleinstellungenActivity extends AppCompatActivity {

    /*
     * Steuerungsvariablen
     */

    /* Läd und verwaltet ein Array aus "strings.xml". */
    private ArrayAdapter<CharSequence> spielerAdapter;

    private List<String> sekundenRundezeit;
    private List<String> sekundenRundenzeitMitNull;

    private String spielerSpielauswhal = Konstanten.SPIELZEIT_OHNE_ZEIT;

    private int spielerSpinnerMinutenWert = 0;
    private int spielerSpinnerSekundenWert = 0;

    /*
     * View-Variablen
     */
    private TextView banner;

    private ImageView steinSpielerOZ;
    private ImageView steinSpielerRD;
    private ImageView steinSpielerSD;

    private Button btnOhneZeit;
    private Button btnRundenzeit;
    private Button btnSpieldauer;

    private LinearLayout spielzeit;

    private Spinner spielerSpinnerMinuten;
    private Spinner spielerSpinnerSekunden;

    private TextView zeit;

    private Button spielerBereit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(edu.whs.spin2018.baoapp.R.layout.activity_lokale_spieleinstellungen);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        List<String> minutenRundenzeit = Arrays.asList(getResources().getStringArray(edu.whs.spin2018.baoapp.R.array.minutesRoundTime));
        sekundenRundezeit = Arrays.asList(getResources().getStringArray(edu.whs.spin2018.baoapp.R.array.secondsRoundTime));
        sekundenRundenzeitMitNull = Arrays.asList(getResources().
                getStringArray(edu.whs.spin2018.baoapp.R.array.secondsRoundTimeWithNull));

        List<String> minutenSpieldauer = Arrays.asList(getResources().getStringArray(edu.whs.spin2018.baoapp.R.array.minutesPlayTime));
        List<String> sekundenSpieldauer = Arrays.asList(getResources().getStringArray(edu.whs.spin2018.baoapp.R.array.secondsPlayTime));

        // View-Elemente werden initialisiert.
        initialisiereViews();
        // Listener für die Buttons werden festgelegt.
        setzeButtonClickListener();
        // Größe der PopUp-Fenster für die Spinner wird festgelegt.
        setzePopUpGroesseSpinnerDialog();
        // Listener für die Spinner werden festgelegt.
        setzeSpinnerListener();
        // Listener für den Bereit-Button wird festgelegt.
        setzeBereitButtonListener();
    }

    /**
     * Initialisiert die View-Elemente für den Controller.
     */
    public void initialisiereViews() {

        banner = findViewById(R.id.tv_lokale_spieleinstellungen_banner);

        steinSpielerOZ = findViewById(R.id.stein_spieler_oz);
        steinSpielerRD = findViewById(R.id.stein_spieler_rd);
        steinSpielerSD = findViewById(R.id.stein_spieler_sd);
        steinSpielerOZ.setVisibility(View.VISIBLE);
        steinSpielerRD.setVisibility(View.INVISIBLE);
        steinSpielerSD.setVisibility(View.INVISIBLE);

        btnOhneZeit = findViewById(R.id.btn_ohne_zeit);
        btnRundenzeit = findViewById(R.id.btn_rundenzeit);
        btnSpieldauer = findViewById(R.id.btn_spieldauer);

        spielzeit = findViewById(R.id.spieler_zeit);
        spielzeit.setVisibility(View.INVISIBLE);

        spielerSpinnerMinuten = findViewById(R.id.spinner_spieler_minuten);
        spielerSpinnerSekunden = findViewById(R.id.spinner_spieler_sekunden);

        zeit = findViewById(R.id.tv_zeit);
        zeit.setVisibility(View.INVISIBLE);

        spielerBereit = findViewById(edu.whs.spin2018.baoapp.R.id.lokale_spieleinstellungen_btn_spiel_starten);

        setzeSchatten();
    }

    public void setzeSchatten() {

        ViewUtils.setzeSchatten(banner);

        ViewUtils.setzeSchatten(btnOhneZeit);
        ViewUtils.setzeSchatten(btnRundenzeit);
        ViewUtils.setzeSchatten(btnSpieldauer);

        ViewUtils.setzeSchatten(zeit);

        ViewUtils.setzeSchatten(spielerBereit);
    }

    /**
     * Setzt die OnClick Listener für die Buttons.
     */
    public void setzeButtonClickListener() {
        btnOhneZeit.setOnClickListener(v -> {

            spielerSpielauswhal = Konstanten.SPIELZEIT_OHNE_ZEIT;
            steinSpielerOZ.setVisibility(View.VISIBLE);
            steinSpielerRD.setVisibility(View.INVISIBLE);
            steinSpielerSD.setVisibility(View.INVISIBLE);

            pruefeUebereinstimmungFuerButtons();

            Toast.makeText(LokaleSpieleinstellungenActivity.this, "playerClicked: " + spielerSpielauswhal, Toast.LENGTH_SHORT).show();
        });

        btnRundenzeit.setOnClickListener(v -> {
            spielerSpielauswhal = Konstanten.SPIELZEIT_RUNDENDAUER;
            steinSpielerOZ.setVisibility(View.INVISIBLE);
            steinSpielerRD.setVisibility(View.VISIBLE);
            steinSpielerSD.setVisibility(View.INVISIBLE);

            pruefeUebereinstimmungFuerButtons();

            Toast.makeText(LokaleSpieleinstellungenActivity.this, "playerClicked: " + spielerSpielauswhal, Toast.LENGTH_SHORT).show();
        });

        btnSpieldauer.setOnClickListener(v -> {
            spielerSpielauswhal = Konstanten.SPIELZEIT_SPIELDAUER;
            steinSpielerOZ.setVisibility(View.INVISIBLE);
            steinSpielerRD.setVisibility(View.INVISIBLE);
            steinSpielerSD.setVisibility(View.VISIBLE);

            pruefeUebereinstimmungFuerButtons();

            Toast.makeText(LokaleSpieleinstellungenActivity.this, "playerClicked: " + spielerSpielauswhal, Toast.LENGTH_SHORT).show();
        });
    }

    /**
     * Setzt die PopUp-Fenstergröße der Spinner.
     */
    public void setzePopUpGroesseSpinnerDialog() {

        android.widget.ListPopupWindow popupWindow;

        int popUpSize = 400;

        try {
            Field popup = Spinner.class.getDeclaredField("mPopup");
            popup.setAccessible(true);

            // Get private mPopup member variable and try cast to ListPopupWindow
            popupWindow = (android.widget.ListPopupWindow) popup.get(spielerSpinnerMinuten);
            // Set popupWindow height to 500px
            popupWindow.setHeight(popUpSize);

            popupWindow = (android.widget.ListPopupWindow) popup.get(spielerSpinnerSekunden);
            popupWindow.setHeight(popUpSize);

        } catch (NoClassDefFoundError | ClassCastException | NoSuchFieldException |
                IllegalAccessException e) {
            // silently fail...
        }
    }

    /**
     * Bindet Listener an die Spinner-Elemente um zu überprüfen, welches Item aus dem Spinner
     * gewählt wurde.
     */
    public void setzeSpinnerListener() {

        spielerSpinnerMinuten.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                spielerSpinnerMinutenWert = Integer.parseInt(parent.getItemAtPosition(pos) + "");
                pruefeUebereinstimmungFuerSpinner(spielerSpinnerMinutenWert, Konstanten.SPIELERTYP_SPIELER);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // Another interface callback
            }
        });

        spielerSpinnerSekunden.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                spielerSpinnerSekundenWert = Integer.parseInt(parent.getItemAtPosition(pos) + "");
                pruefeUebereinstimmungFuerSpinner(-1, Konstanten.SPIELERTYP_KEINER);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // Another interface callback
            }
        });
    }

    /**
     * Bindet onClickListener an den "Spiel starten"-Button. Wird dieser gedrückt, startet das Spiel.
     */
    public void setzeBereitButtonListener() {

        spielerBereit.setOnClickListener(view -> {

            Intent startGame = new Intent(LokaleSpieleinstellungenActivity.this,
                    BaoSpielActivity.class);
            startGame.putExtra(Konstanten.EXTRA_SPIELTYP, BaoSpielPresenter.SPIEL_TYP_LOKALES_SPIEL);
            startGame.putExtra(Konstanten.EXTRA_SPIELMODUS, spielerSpielauswhal);
            startGame.putExtra(Konstanten.EXTRA_GEGNER, Konstanten.GEGNER_GAST);
            startGame.putExtra(Konstanten.EXTRA_SPIELZEIT_MINUTEN, spielerSpinnerMinutenWert);
            startGame.putExtra(Konstanten.EXTRA_SPIELZEIT_SEKUNDEN, spielerSpinnerSekundenWert);
            startGame.putExtra(Konstanten.EXTRA_GEGNER_NAME,Konstanten.GEGNER_GAST);
            startActivity(startGame);
        });
    }

    /**
     * Überprüft den ausgewählten Spielmodus. Ist der Modus "keine Zeit", werden die
     * Zeiteinstellungen unsichtbar.
     */
    public void pruefeUebereinstimmungFuerButtons() {

        if (!spielerSpielauswhal.equals(Konstanten.SPIELZEIT_OHNE_ZEIT)) {

            spielzeit.setVisibility(View.VISIBLE);
            zeit.setVisibility(View.VISIBLE);

            switch (spielerSpielauswhal) {
                case Konstanten.SPIELZEIT_RUNDENDAUER:
                    spielerAdapter = ArrayAdapter.createFromResource(this,
                            edu.whs.spin2018.baoapp.R.array.minutesRoundTime, android.R.layout.simple_spinner_item);
                    spielerAdapter.setDropDownViewResource(android.R.layout.
                            simple_spinner_dropdown_item);
                    spielerSpinnerMinuten.setAdapter(spielerAdapter);
                    spielerAdapter = ArrayAdapter.createFromResource(this,
                            edu.whs.spin2018.baoapp.R.array.secondsRoundTime, android.R.layout.simple_spinner_item);
                    spielerAdapter.setDropDownViewResource(android.R.layout.
                            simple_spinner_dropdown_item);
                    spielerSpinnerSekunden.setAdapter(spielerAdapter);
                    spielerAdapter = ArrayAdapter.createFromResource(this,
                            edu.whs.spin2018.baoapp.R.array.minutesRoundTime, android.R.layout.simple_spinner_item);
                    spielerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
                    break;

                case Konstanten.SPIELZEIT_SPIELDAUER:
                    spielerAdapter = ArrayAdapter.createFromResource(this,
                            edu.whs.spin2018.baoapp.R.array.minutesPlayTime, android.R.layout.simple_spinner_item);
                    spielerAdapter.setDropDownViewResource(android.R.layout.
                            simple_spinner_dropdown_item);
                    spielerSpinnerMinuten.setAdapter(spielerAdapter);
                    spielerAdapter = ArrayAdapter.createFromResource(this,
                            edu.whs.spin2018.baoapp.R.array.secondsPlayTime, android.R.layout.simple_spinner_item);
                    spielerAdapter.setDropDownViewResource(android.R.layout.
                            simple_spinner_dropdown_item);
                    spielerSpinnerSekunden.setAdapter(spielerAdapter);
                    break;
            }

        } else {

            spielzeit.setVisibility(View.INVISIBLE);
            zeit.setVisibility(View.INVISIBLE);
        }
    }

    /**
     * Überprüft die ausgewählte Einstellung für die Spielzeit. Ist die Minutenzahl größer 0, wird
     * ein anderes Array in den Spinner für die Sekunden geladen. (Benutzersteuerung)
     *
     * @param minutes    Die Spielerminuten.
     * @param playerType Spielertyp, kann Spieler oder Gegner sein.
     */
    public void pruefeUebereinstimmungFuerSpinner(int minutes, String playerType) {

        if (minutes > 0 && playerType.equals(Konstanten.SPIELERTYP_SPIELER)) {
            spielerAdapter = ArrayAdapter.createFromResource(this,
                    edu.whs.spin2018.baoapp.R.array.secondsRoundTimeWithNull, android.R.layout.simple_spinner_item);
            spielerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spielerSpinnerSekunden.setAdapter(spielerAdapter);

            spielerSpinnerSekunden.setSelection(sekundenRundenzeitMitNull.
                    indexOf("" + spielerSpinnerSekundenWert));

            if (spielerSpielauswhal.equals(Konstanten.SPIELZEIT_SPIELDAUER)) {
                spielerAdapter = ArrayAdapter.createFromResource(this,
                        edu.whs.spin2018.baoapp.R.array.secondsPlayTime, android.R.layout.simple_spinner_item);
                spielerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                spielerSpinnerSekunden.setAdapter(spielerAdapter);
            }

        } else if (minutes == 0 && playerType.equals(Konstanten.SPIELERTYP_SPIELER)) {

            spielerAdapter = ArrayAdapter.createFromResource(this, edu.whs.spin2018.baoapp.R.array.secondsRoundTime,
                    android.R.layout.simple_spinner_item);
            spielerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spielerSpinnerSekunden.setAdapter(spielerAdapter);

            spielerSpinnerSekunden.setSelection(sekundenRundezeit.
                    indexOf("" + spielerSpinnerSekundenWert));
        }
    }
}
