/* Copyright 2014-2023 askanimus@gmail.com */

/* This File is part of "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2).
 *
 * "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2).  If not, see <http://www.gnu.org/licenses/>.
 *
 * Diese Datei ist Teil von "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2).
 *
 * "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2) ist Freie Software: Sie können es unter den Bedingungen
 * der GNU General Public License, wie von der Free Software Foundation,
 * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren
 * veröffentlichten Version, weiter verteilen und/oder modifizieren.
 *
 * "Arbeitszeitkonto" (askanimus.arbeitszeiterfassung2) wird in der Hoffnung, dass es nützlich sein wird, aber
 * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
 * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
 * Siehe die GNU General Public License für weitere Details.
 *
 * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
 * Programm erhalten haben. Wenn nicht, siehe <https://www.gnu.org/licenses/>.
 */
package askanimus.arbeitszeiterfassung2.setup;

import android.content.Context;
import android.text.InputFilter;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.abwesenheiten.AbwesenheitListe;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.gallerie.IconGalleryAdapter;

public class AbwesenheitDefinitionViewAdapter
        extends RecyclerView.Adapter<AbwesenheitDefinitionViewAdapter.ViewHolder>
{
    private Context mContext;
    private Arbeitsplatz mArbeitsplatz;
    private AbwesenheitListe mAbwesenheiten;
    private ItemClickListener mClickListener;
    private int[] mIcon;
    private int[] mWirkung;

    private int openPosition = -1;
    private ViewHolder openHolder = null;

    private boolean isMenuOpen = false;

    public void setUp (
            Context context, Arbeitsplatz job, ItemClickListener clickListener) {
        mContext = context;
        mAbwesenheiten = job.getAbwesenheiten();
        mArbeitsplatz = job;
        mClickListener = clickListener;
        mWirkung = ASettings.res.getIntArray(R.array.pref_wirkung_werte);
        String[] mI = ASettings.res.getStringArray(R.array.iconliste);
        mIcon = new int[mI.length];
        for (int i = 0; i < mI.length; i++) {
            mIcon[i] = ASettings.res.getIdentifier(
                    mI[i], "drawable", "askanimus.arbeitszeiterfassung2");
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        mContext = parent.getContext();
        View view = LayoutInflater.from(mContext)
            .inflate(R.layout.item_abwesenheit_definition, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull AbwesenheitDefinitionViewAdapter.ViewHolder holder, int position) {
        if (position < getItemCount()) {
            Abwesenheit abw = getItem(position);
            holder.mTitel.setText(abw.getName());

            if (position <= Abwesenheit.RUHETAG) {
                holder.mDelete.setVisibility(View.GONE);
            } else {
                holder.mDelete.setVisibility(View.VISIBLE);
            }

            // die Werte der Abwesenheit anzeigen oder verbergen
            if (openPosition == position) {
                openHolder = holder;
                holder.mErweitert.setVisibility(View.VISIBLE);
                holder.iArrow.setImageResource(R.drawable.arrow_up);
                updateView(holder, position);
            }
        }
    }

    private void updateView(ViewHolder holder, int position) {
        Abwesenheit abw = getItem(position);

        if (abw != null) {
            holder.wName.setText(abw.getName());
            holder.wKurz.setText(abw.getKuerzel());
            holder.sWirkung.setSelection(getWirkungIndex(abw.getWirkung()));
            holder.sWirkung.setEnabled(position > Abwesenheit.RUHETAG);

            if (abw.getKategorie() >= 0) {
                holder.sKategorie.setSelection(abw.getKategorie());
                holder.sKategorie.setEnabled(position > Abwesenheit.RUHETAG);
            } else {
                holder.sKategorie.setVisibility(View.GONE);
                holder.tKategorie.setVisibility(View.GONE);
            }

            int icon = abw.getIcon_Id();
            if (icon == R.drawable.leer) {
                icon = R.drawable.noicon;
            }
            holder.wIcon.setImageResource(icon);


            //Klickhandler registrieren
            holder.wName.setOnClickListener(v -> {
                final InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final EditText input = new EditText(mContext);
                input.setInputType(InputType.TYPE_CLASS_TEXT);
                input.setLines(1);
                input.setText(abw.getName());
                input.setSelection(input.getText().length());
                input.setFocusableInTouchMode(true);
                input.requestFocus();
                input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
                if (imm != null) {
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
                //Längenbegrenzung des Inputstrings
                InputFilter[] fa = new InputFilter[1];
                fa[0] = new InputFilter.LengthFilter(ISettings.LAENGE_NAME);
                input.setFilters(fa);

                new AlertDialog.Builder(mContext)
                        .setTitle(mContext.getString(R.string.bezeichnung))
                        .setView(input)
                        .setPositiveButton(mContext.getString(android.R.string.ok), (dialog, whichButton) -> {
                            abw.setName(input.getText().toString());
                            holder.wName.setText(abw.getName());
                            assert imm != null;
                            imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
                            holder.mTitel.setText(abw.getName());
                        }).setNegativeButton(mContext.getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    assert imm != null;
                    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);

                }).show();
            });

            holder.wKurz.setOnClickListener(v -> {
                final InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final EditText input = new EditText(mContext);
                input.setInputType(InputType.TYPE_CLASS_TEXT);
                input.setLines(1);
                input.setText(abw.getKuerzel());
                input.setSelection(input.getText().length());
                input.setFocusableInTouchMode(true);
                input.requestFocus();
                input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
                //Längenbegrenzung des Inputstrings
                InputFilter[] fk = new InputFilter[1];
                fk[0] = new InputFilter.LengthFilter(ISettings.LAENGE_NAME_KURZ);
                input.setFilters(fk);
                if (imm != null) {
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }

                new android.app.AlertDialog.Builder(mContext)
                        .setTitle(mContext.getString(R.string.k_bezeichnung))
                        .setView(input)
                        .setPositiveButton(mContext.getString(android.R.string.ok), (dialog, whichButton) -> {
                            abw.setKuerzel(input.getText().toString());
                            holder.wKurz.setText(abw.getKuerzel());
                            assert imm != null;
                            imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
                        }).setNegativeButton(mContext.getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    assert imm != null;
                    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);

                }).show();
            });

            holder.sWirkung.setOnTouchListener((v, event) -> {
                isMenuOpen = true;
                v.performClick();
                return false;
            });
            holder.sWirkung.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int selection, long id) {
                    if (abw.getWirkung() != mWirkung[selection]) {
                        abw.setWirkung(mWirkung[selection]);
                        mArbeitsplatz.setNeuberechnung();
                    }
                    isMenuOpen = false;
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                    isMenuOpen = false;
                }
            });

            holder.sKategorie.setOnTouchListener((v, event) -> {
                isMenuOpen = true;
                v.performClick();
                return false;
            });
            holder.sKategorie.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int selection, long id) {
                    if (abw.getKategorie() != selection) {
                        abw.setKategorie(selection);
                        isMenuOpen = false;
                        mArbeitsplatz.setNeuberechnung();
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                    isMenuOpen = false;
                }
            });

            holder.wIcon.setOnClickListener(v -> {
                RecyclerView view = new RecyclerView(mContext);
                final IconGalleryAdapter iconGalleryAdapter
                        = new IconGalleryAdapter(mIcon, abw.getIcon_Id());
                GridLayoutManager layoutManger = new GridLayoutManager(mContext, 4);
                view.setLayoutManager(layoutManger);
                view.setAdapter(iconGalleryAdapter);
                new AlertDialog.Builder(mContext)
                        .setTitle(mContext.getString(R.string.icon))
                        .setView(view)
                        .setPositiveButton(mContext.getString(android.R.string.ok), (dialog, whichButton) -> {
                            int pos = iconGalleryAdapter.getPositionSelect();
                            abw.setIcon_Id(mIcon[pos]);
                            if (pos > 0) {
                                holder.wIcon.setImageResource(mIcon[pos]);
                            } else {
                                holder.wIcon.setImageResource(R.drawable.noicon);
                            }
                        }).setNegativeButton(mContext.getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                }).show();
            });

            holder.wHelp.setOnClickListener(v -> new AlertDialog.Builder(mContext)
                    .setTitle(mContext.getString(R.string.wirkung_zeiten))
                    .setView(R.layout.fragment_help_wirkungen)
                    .setNeutralButton(mContext.getString(
                            android.R.string.ok),
                            (dialog, whichButton) -> {
                            }).show());
        }
    }

    boolean isMenuOpen(ViewHolder holder){
        return isMenuOpen && holder == openHolder;
    }

    public void closeOpenItem() {
        if (openHolder != null) {
            openHolder.mErweitert.setVisibility(View.GONE);
            openHolder.iArrow.setImageResource(R.drawable.arrow_down);
            openHolder = null;
        }
        openPosition = -1;
        isMenuOpen = false;
    }

    @Override
    public int getItemCount() {
        if(mAbwesenheiten != null) {
            return mAbwesenheiten.sizeAktive();
        }

        return 0;
    }

    Abwesenheit getItem(int position) {
        if (position < getItemCount()) {
            return mAbwesenheiten.getAktive(position);
        }
        return null;
    }

    private int getWirkungIndex(int wirkung) {
        int i;
        for (i = 0; i < mWirkung.length; i++) {
            if (mWirkung[i] == wirkung)
                break;
        }
        return i;
    }

    // öffne neu angelegte Abwesenheit (also die letzte in der Liste)
    public void openNew() {
        // die zuvor offene Abwesenheit schliessen
        if (openHolder != null) {
            openHolder.mErweitert.setVisibility(View.GONE);
            openHolder.iArrow.setImageResource(R.drawable.arrow_down);
        }

        // neue Abwesenheit als geöffnet markieren
        openPosition = getItemCount() - 1;
        mClickListener.onExpand(openPosition);
        isMenuOpen = false;
    }

    // Rückmeldung an Eltern
    public interface ItemClickListener {
        void onAbwesenheitDelete(int index);

        void onExpand(int position);
    }


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView mTitel;
        ImageView mDelete;
        ImageView iArrow;
        RelativeLayout mErweitert;
        TextView wName;
        TextView wKurz;
        ImageView wIcon;
        Spinner sWirkung;
        TextView tKategorie;
        Spinner sKategorie;
        ImageView wHelp;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            mTitel = itemView.findViewById(R.id.IA_name_kopf);
            mDelete = itemView.findViewById(R.id.IA_button_kopf);
            iArrow = itemView.findViewById(R.id.IA_arrow);
            mErweitert = itemView.findViewById(R.id.IA_frame_detail);
            wName = itemView.findViewById(R.id.IA_wert_abwesenheitname);
            wKurz = itemView.findViewById(R.id.IA_wert_kuerzel);
            wIcon = itemView.findViewById(R.id.IA_wert_icon);
            sWirkung = itemView.findViewById(R.id.IA_spinner_wirkung);
            sKategorie = itemView.findViewById(R.id.IA_spinner_kategorie);
            tKategorie = itemView.findViewById(R.id.IA_titel_kategorie);
            wHelp = itemView.findViewById(R.id.IA_button_help);

            RelativeLayout bTitel = itemView.findViewById(R.id.IA_kopf_frame);
            bTitel.setBackgroundColor(mArbeitsplatz.getFarbe_Tag());
            bTitel.setOnClickListener(v -> expand(getAdapterPosition()));

            if (mClickListener != null) {
                mDelete.setOnClickListener(v -> mClickListener.onAbwesenheitDelete(getAdapterPosition()));
            }
        }

        void expand(int position) {
            // den alten Inhalt schliessen
            if (openHolder != null) {
                openHolder.mErweitert.setVisibility(View.GONE);
                openHolder.iArrow.setImageResource(R.drawable.arrow_down);
                isMenuOpen = false;
            }

            // ist auf eine offne Abwesenheit getippt worden, diese als geschlossen markieren
            if (openHolder == this) {
                openHolder = null;
                openPosition = -1;
            } else {
                openPosition = position;
                openHolder = this;
                iArrow.setImageResource(R.drawable.arrow_up);
                updateView(this, position);

                // Erweiterung öffnen
                mErweitert.setVisibility(View.VISIBLE);
                mClickListener.onExpand(position);
            }
        }
    }
}
