/* 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.arbeitstag;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Calendar;

import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitsschicht.Arbeitsschicht;
import askanimus.arbeitszeiterfassung2.Datum;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.Uhrzeit;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.IZusatzfeld;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.ZusatzWertViewAdapter;

/**
 * @author askanimus@gmail.com on 06.12.15.
 */
public class ArbeitstagExpandListAdapter extends BaseExpandableListAdapter {
    private final Context mContext;

    private final ArbeitstagListeCallbacks mCallback;

    private final ArrayList<Arbeitstag> mTage;

    // Einstellungen zur Anzeige und Eingabe
    private final Boolean isEinsatzort;

    private final int mZeilen;

    public ArbeitstagExpandListAdapter(Context context, ArrayList<Arbeitstag> tagesliste, ArbeitstagListeCallbacks cb) {
        mContext = context;
        mTage = tagesliste;
        mCallback = cb;

        isEinsatzort = ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_WERT_EORT);

        if(mTage.get(mTage.size()-1).getKalender().liegtNach(ASettings.letzterAnzeigeTag)){
           int i=0;
           while(!mTage.get(i).getKalender().liegtNach(ASettings.letzterAnzeigeTag)){
               i++;
           }
           mZeilen = i;
        } else {
            mZeilen = mTage.size();
        }
    }


    @Override
    public int getGroupCount() {
        return mZeilen;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
         // die Anzahl Schichten pro Tag
        return getGroup(groupPosition).getSchichtAnzahl();
    }

    @Override
    public Arbeitstag getGroup(int groupPosition) {
        int pos;
        // den richtigen Tag suchen
        if (ASettings.mPreferenzen.getBoolean(ISettings.KEY_ANZEIGE_UMG_SORT, false)) {
            pos = mTage.size() - 1 - groupPosition;
        } else {
            pos = groupPosition;
        }
        if (pos >= mTage.size())
            pos = mTage.size() - 1;
        else if (pos < 0)
            pos = 0;

        return mTage.get(pos);
    }

    @Override
    public Arbeitsschicht getChild(int groupPosition, int childPosition) {
        return getGroup(groupPosition).getSchicht(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getGroupView(final int groupPosition, boolean isExpanded, View contentView, ViewGroup parent) {
        LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if (mInflater != null) {
            contentView = mInflater.inflate(R.layout.item_arbeitstag, parent, false);

            final Arbeitstag mTag;
            // den richtigen Tag suchen
            mTag = getGroup(groupPosition);

            // die Anzeigeelemente des Tages
            RelativeLayout cInfo;
            RelativeLayout cRahmen;
            TextView tTag;
            TextView tDatum;
            TextView tNetto;
            TextView tSaldo;
            ImageView iEdit;
            LinearLayout cIcons;

            cInfo = contentView.findViewById(R.id.AT_box_basis);
            cRahmen = contentView.findViewById(R.id.AT_box_rahmen);
            tTag = contentView.findViewById(R.id.AT_wert_tag);
            tDatum = contentView.findViewById(R.id.AT_wert_datum);
            tNetto = contentView.findViewById(R.id.AT_wert_netto);
            tSaldo = contentView.findViewById(R.id.AT_wert_saldo);
            iEdit = contentView.findViewById(R.id.AT_button_edit);
            cIcons = contentView.findViewById(R.id.AT_box_icons);

            ////////////////////////// Werte setzen ////////////////////////////////////////////////
            // Datum und Farbe
            tTag.setText(mTag.getKalender().getString_Wochentag(false));
            tDatum.setText(mTag.getKalender().getString_Datum(mContext));
            switch (mTag.getKalender().get(Calendar.DAY_OF_WEEK)) {
                case Calendar.SATURDAY:
                    cInfo.setBackgroundColor(ASettings.cHintergrundSa);
                    break;
                case Calendar.SUNDAY:
                    cInfo.setBackgroundColor(ASettings.cHintergrundSo);
                    break;
                default:
                    cInfo.setBackgroundColor(ASettings.aktJob.getFarbe_Tag());
            }
            if (mTag.getKalender().istGleich(ASettings.aktDatum)) {
                cRahmen.setBackground(
                        ResourcesCompat.getDrawable(
                                ASettings.res,
                                R.drawable.rahmen_tagakt,
                                mContext.getTheme()));
            }

            // Nettoarbeitszeit
            Uhrzeit mZeit = new Uhrzeit(mTag.getTagNetto());
            tNetto.setText(mZeit.getStundenString(
                    true,
                    ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
            );

            mZeit.set(mZeit.getAlsMinuten() - mTag.getTagSollNetto());

            if (mZeit.getAlsMinuten() != 0 && ASettings.mPreferenzen.getBoolean(ISettings.KEY_ANZEIGE_ERW_SALDO, false)) {
                tSaldo.setText(mZeit.getStundenString(
                        true,
                        ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
                );
                tSaldo.setTextColor((mZeit.getAlsMinuten() < 0) ?
                        ASettings.cNegativText : ASettings.cPositivText
                );
            } else {
                tSaldo.setVisibility(View.GONE);
            }

            // Der Clickhandler für das Bearbeiten - Icon
            // Nach dem Aufzeichnugsende den Button deaktiviren
            if (ASettings.aktJob.isEndeAufzeichnung(ASettings.aktDatum)) {
                iEdit.setVisibility(View.INVISIBLE);
            } else {
                iEdit.setOnClickListener(v -> mCallback.onEditArbeitstag(mTag.getKalender()));
            }

            //////////////////////////////////////////// Icons der Schichten darstellen ////////////
            IconListadapter mIconAdapter = new IconListadapter();
            mIconAdapter.setUp(mTag);
            for (int i = 0; i < mIconAdapter.getCount(); i++) {
                cIcons.addView(mIconAdapter.getView(i, cIcons, parent));
            }
        }
        return contentView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View contentView, ViewGroup parent) {

        LayoutInflater mInflater =
                (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if (mInflater != null) {
            contentView = mInflater.inflate(R.layout.item_arbeitsschicht_info, parent, false);

            final Arbeitsschicht vSchicht = getChild(groupPosition, childPosition);

            Abwesenheit sAbwesenheit = vSchicht.getAbwesenheit();
            Uhrzeit mZeit = new Uhrzeit(vSchicht.getNetto());

            // Die Anzeigeelemente
            contentView.setBackgroundColor(
                    (childPosition % 2 == 0) ?
                            ASettings.aktJob.getFarbe_Zeile_gerade() :
                            ASettings.aktJob.getFarbe_Zeile_ungerade()
            );

            // Abwesenheitsicon
            ImageView iAbwesenheit = contentView.findViewById(R.id.SI_icon_abwesenheit);
            iAbwesenheit.setImageResource(sAbwesenheit.getIcon_Id());

            //Schichtname
            TextView tSchichtname = contentView.findViewById(R.id.SI_wert_name);
            if (ASettings.aktJob.isTeilschicht() || vSchicht.getWirkung() == Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV) {
                tSchichtname.setText(vSchicht.getName());
            } else
                tSchichtname.setVisibility(View.GONE);

            // optionale Werte
            LinearLayout cZusatzwerte = contentView.findViewById(R.id.SI_box_zusatzwerte);

            // Netto
            TextView tNetto = contentView.findViewById(R.id.SI_wert_netto);

            // einsatzort
            TextView tEort = contentView.findViewById(R.id.SI_wert_eort);

            // Zeiten
            TextView tZeitraum = contentView.findViewById(R.id.SI_wert_zeiten);
            String sZeitraum;


            //boolean isZusatzwerte = false;
            switch (sAbwesenheit.getWirkung()) {
                case Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV:
                    if (sAbwesenheit.getKategorie() == Abwesenheit.KAT_ARBEITSZEIT) {
                        mZeit.set(vSchicht.getVon());
                        sZeitraum = mZeit.getUhrzeitString() + " -";
                        mZeit.set(vSchicht.getBis());
                        sZeitraum += mZeit.getUhrzeitString() + " ";
                        sZeitraum += mContext.getString(R.string.pause) + ": ";
                        mZeit.set(vSchicht.getPause());
                        sZeitraum += mZeit.getStundenString(
                                true,
                                ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL)
                        );


                    } else {
                        mZeit.set(vSchicht.getBrutto());
                        sZeitraum = sAbwesenheit.getName();
                    }
                    //einsatzort
                    if (isEinsatzort && vSchicht.getIdEinsatzort() > 0)
                        tEort.setText(vSchicht.getNameEinsatzort());
                    else
                        tEort.setVisibility(View.GONE);
                    // Zeitspanne anzeigen
                    tZeitraum.setText(sZeitraum);
                    // Netto
                    mZeit.set(vSchicht.getNetto());
                    tNetto.setText(mZeit.getStundenString(
                            false,
                            ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
                    );
                    break;
                case Abwesenheit.WIRKUNG_IST_PLUS_PAUSCHAL:
                    // Ausgabe der Wirkung ( an der Position des Einsatzortes )
                    tEort.setText(R.string.wirkung_plus_pauschal);
                    sZeitraum = sAbwesenheit.getName();
                    sZeitraum += " ("
                            + vSchicht.getBis()
                            + " %)";
                    tZeitraum.setText(sZeitraum);
                    mZeit.set(vSchicht.getNetto());
                    tNetto.setText(mZeit.getStundenString(
                            false,
                            ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
                    );
                    // Zusatzwerte ausblenden
                    cZusatzwerte.setVisibility(View.GONE);
                    break;
                case Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV:
                    sZeitraum = sAbwesenheit.getName();
                    tZeitraum.setText(sZeitraum);
                    // Ausgabe der Wirkung ( an der Position des Einsatzortes )
                    tEort.setText(R.string.wirkung_minus_stunden_effektiv);
                    tEort.setTextColor(ASettings.cManuellText);
                    // Anzahl der Stunden die abgezogen werden ( an der Position Netto)
                    mZeit.set(vSchicht.getMinusSollMinuten());
                    tNetto.setText(mZeit.getStundenString(
                            false,
                            ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
                    );
                    tNetto.setTextColor(ASettings.cManuellText);
                    // Zusatzwerte ausblenden
                    cZusatzwerte.setVisibility(View.GONE);
                    break;
                case Abwesenheit.WIRKUNG_SOLL_MINUS_TAGE:
                    // Ausgabe der Wirkung ( an der Position des Einsatzortes )
                    tEort.setText(R.string.wirkung_minus_tage);
                    tEort.setTextColor(ASettings.cManuellText);
                    sZeitraum = sAbwesenheit.getName();
                    sZeitraum += " ("
                            + vSchicht.getBis()
                            + " %)";
                    tZeitraum.setText(sZeitraum);
                    tNetto.setText(ASettings.zahlenformat.format((float) vSchicht.getBis() / 100));
                    tNetto.setTextColor(ASettings.cManuellText);
                    // Zusatzwerte ausblenden
                    cZusatzwerte.setVisibility(View.GONE);
                    break;
                case Abwesenheit.WIRKUNG_SOLL_MINUS_STUNDEN:
                    // Ausgabe der Wirkung ( an der Position des Einsatzortes )
                    tEort.setText(R.string.wirkung_minus_stunden);
                    tEort.setTextColor(ASettings.cManuellText);
                    sZeitraum = sAbwesenheit.getName();
                    sZeitraum += " ("
                            + vSchicht.getBis()
                            + " %)";
                    tZeitraum.setText(sZeitraum);
                    mZeit.set(vSchicht.getMinusSollMinuten());
                    tNetto.setText(mZeit.getStundenString(
                            false,
                            ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL))
                    );
                    tNetto.setTextColor(ASettings.cManuellText);
                    // Zusatzwerte ausblenden
                    cZusatzwerte.setVisibility(View.GONE);
                    break;
                default:
                    if (sAbwesenheit.getKategorie() == Abwesenheit.KAT_KEINESCHICHT) {
                        tZeitraum.setText("");
                        // einsatzort ausblenden
                        tEort.setVisibility(View.GONE);
                        // Zusatzwerte ausblenden
                        cZusatzwerte.setVisibility(View.GONE);
                        // Netto ausblenden
                        tNetto.setVisibility(View.GONE);
                    } else {
                        //isZusatzwerte = false;
                        tZeitraum.setText(sAbwesenheit.getName());
                        // einsatzort Wirkung anzeigen
                        tEort.setText(R.string.wirkung_keine);
                        // Netto ausblenden
                        tNetto.setVisibility(View.INVISIBLE);
                    }
            }

            if (sAbwesenheit.getKategorie() != Abwesenheit.KAT_KEINESCHICHT) {
                //einsatzort
                if (isEinsatzort && vSchicht.getIdEinsatzort() > 0)
                    tEort.setText(vSchicht.getNameEinsatzort());
            }

            // die Zusatzwerte anzeigen
            if (vSchicht.getZusatzfelder(IZusatzfeld.TEXT_VOLL).size() > 0) {
                RecyclerView gZusatzwerte = contentView.findViewById(R.id.SI_grid_zusatzwerte);
                ZusatzWertViewAdapter viewAdapter = new ZusatzWertViewAdapter(
                        vSchicht.getZusatzfelder(IZusatzfeld.TEXT_VOLL).getListe(),
                        null,
                        ZusatzWertViewAdapter.VIEW_INFO);
                GridLayoutManager layoutManger = new GridLayoutManager(
                        mContext,
                        IZusatzfeld.MAX_COLUM);
                layoutManger.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        return vSchicht.getZusatzfelder(IZusatzfeld.TEXT_VOLL).get(position).getColums();
                    }
                });
                gZusatzwerte.setLayoutManager(layoutManger);
                gZusatzwerte.setAdapter(viewAdapter);
            } else {
                cZusatzwerte.setVisibility(View.GONE);
            }

        }

        return contentView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }


    /*
     * Callback Interfaces
     */
    public interface ArbeitstagListeCallbacks {
        /**
         * Aufgerufen wenn der Tag bearbeitet werden soll
         */
        void onEditArbeitstag(Datum datum);
    }


    ////////////////////////////////////// Listadapter für Icons //////////////////////////////////
    private class IconListadapter extends BaseAdapter{
        private ArrayList<Integer> mIcons;

        protected void setUp(Arbeitstag tag){
            boolean isDoppelt;
            int idIcon;
            mIcons = new ArrayList<>();

            for (int i = 0; i < tag.getSchichtAnzahl(); i++) {
                idIcon = tag.getSchicht(i).getAbwesenheit().getIcon_Id();
                if (idIcon != R.drawable.leer) {
                    isDoppelt = false;
                    for (int s = 0; (s < mIcons.size() && !isDoppelt); s++) {
                        isDoppelt = mIcons.get(s) == idIcon;
                                            }
                    if (!isDoppelt)
                        mIcons.add(idIcon);
                }
            }
        }

        @Override
        public int getCount() {
            return mIcons.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            if (mInflater != null) {
                convertView = mInflater.inflate(R.layout.view_icon_abwsenheit, parent, false);

                ImageView iIcon = convertView.findViewById(R.id.IV_icon);
                iIcon.setImageResource(mIcons.get(position));
            }
            return convertView;
        }
    }
}
