/*
 * Copyright (c) 2014 - 2024 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.stempeluhr;

import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
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.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

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

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

import askanimus.arbeitszeiterfassung2.MainActivity;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.Uhrzeit;
import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.abwesenheiten.AbwesenheitListadapter;
import askanimus.arbeitszeiterfassung2.arbeitsmonat.Arbeitsmonat;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitsschicht.Arbeitsschicht;
import askanimus.arbeitszeiterfassung2.arbeitsschicht.SchichtDefault;
import askanimus.arbeitszeiterfassung2.arbeitstag.Arbeitstag;
import askanimus.arbeitszeiterfassung2.einsatzort.Einsatzort;
import askanimus.arbeitszeiterfassung2.einsatzort.EinsatzortAuswahlDialog;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.widget.WidgetStatus;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.IZusatzfeld;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.TextFeldTextListe;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.Textfeld;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.ZusatzWertViewAdapter;

public class StempeluhrExpandListAdapter
        extends RecyclerView.Adapter<StempeluhrExpandListAdapter.ViewHolder>
        implements ISettings {
    private Context mContext;
    private StempeluhrListe mStempeluhren;
    private ItemClickListener mClickListener;
    private LayoutInflater mInflater;

    private ArrayList<ViewHolder> mHolderList = new ArrayList<>();

    public void setUp(
            Context context,
            StempeluhrListe liste,
            ItemClickListener clickListener
    ) {
        mContext = context;
        mStempeluhren = liste;
        mInflater = LayoutInflater.from(context);
        mClickListener = clickListener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //LayoutInflater mInflater = LayoutInflater.from(parent.getContext());
        ViewHolder neuerHolder = new ViewHolder(mInflater.inflate(R.layout.item_stempeluhr, parent, false));
        mHolderList.add(neuerHolder);
        return neuerHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull StempeluhrExpandListAdapter.ViewHolder holder, int position) {
        StempeluhrStatus mStempeluhr = getItem(holder.getAdapterPosition());

        if (mStempeluhr != null) {
            Arbeitsplatz mArbeitsplatz = mStempeluhr.getArbeitsplatz();
            holder.mTitel.setText(mArbeitsplatz.getName());
            holder.mTitel.setTextColor(mArbeitsplatz.getFarbe_Schrift_Titel());
            holder.wStempelzeit.setTextColor(mArbeitsplatz.getFarbe_Schrift_Titel());
            holder.wPausezeit.setTextColor(mArbeitsplatz.getFarbe_Schrift_Titel());
            holder.bAll.setBackgroundColor(mArbeitsplatz.getFarbe_Schicht_gerade());
            holder.bTitel.setBackgroundColor(mArbeitsplatz.getFarbe());

            // die Auswahl der Abwesenheiten, begrenzt auf die Kategorie Arbeitszeit
            AbwesenheitListadapter spinnerArrayAdapter = new AbwesenheitListadapter(
                    mContext,
                    mStempeluhr.getArbeitsplatz(),
                    Abwesenheit.KAT_ARBEITSZEIT);
            holder.sAbwesenheit.setAdapter(spinnerArrayAdapter);
            holder.sAbwesenheit.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    if (id != mStempeluhr.getAbwesenheit().getID()) {
                        spinnerArrayAdapter.setSelectAbwesenheit(id);
                        mStempeluhr.setAbwesenheit(spinnerArrayAdapter.getItem(position));
                        notifyItemChanged(position);
                        //updateStempelUhr(position, -1);
                        ((TextView) view).setTypeface(null, Typeface.BOLD);
                    }
                }

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

            // die gespeicherte Abwesenheit einstellen
            holder.sAbwesenheit.setSelection(
                    spinnerArrayAdapter.setSelectAbwesenheit(mStempeluhr.getAbwesenheit().getID())
            );

            // Der Einsatzort
            if (mStempeluhr.isEinsatzort()) {
                holder.eortAuswahl = new EinsatzortAuswahlDialog(
                        mContext,
                        new EinsatzortAuswahlDialog.EinsatzortAuswahlDialogCallbacks() {
                            @Override
                            public void onEinsatzortSet(Einsatzort eort) {
                                if (!eort.equals(mStempeluhr.getEinsatzort())) {
                                    mStempeluhr.setEinsatzort(eort);
                                    notifyItemChanged(holder.getAdapterPosition());
                                }
                            }
                        },
                        mArbeitsplatz,
                        ASettings.aktDatum.getTimeInMillis()
                );

                holder.wEinsatzort.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        holder.eortAuswahl.open();
                    }
                });
            } else {
                holder.wEinsatzort.setVisibility(View.GONE);
            }


            // Die Zusatzwerte
            if (mStempeluhr.isZusatzwerte()) {
                ZusatzWertViewAdapter viewAdapter = new ZusatzWertViewAdapter(
                        mStempeluhr.getZusatzwertListe(),
                        holder,
                        ZusatzWertViewAdapter.VIEW_EDIT
                );
                GridLayoutManager layoutManger = new GridLayoutManager(
                        mContext,
                        IZusatzfeld.MAX_COLUM
                );
                layoutManger.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        return mStempeluhr.getZusatzwertListe().get(position).getColums();
                    }
                });
                holder.gZusatzwerte.setLayoutManager(layoutManger);
                holder.gZusatzwerte.setAdapter(viewAdapter);
            } else {
                holder.gZusatzwerte.setVisibility(View.GONE);
            }

            // die Timericons beleben
            holder.iStartPause.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    StempeluhrStatus stempeluhrStatus = getItem(holder.getAdapterPosition());
                    switch (stempeluhrStatus.getStatus()) {
                        case StempeluhrStatus.WIDGET_STATUS_NEU:
                            stempeluhrStatus.start();
                            holder.open();
                            break;
                        case StempeluhrStatus.WIDGET_STATUS_PAUSE:
                            stempeluhrStatus.stopPause();
                            break;
                        case StempeluhrStatus.WIDGET_STATUS_RUN:
                            stempeluhrStatus.startPause();
                            break;
                    }
                    updateStempelUhr(holder.getAdapterPosition(), -1);
                }
            });

            holder.iStop.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    StempeluhrStatus stempeluhrStatus = mStempeluhren.get(holder.getAdapterPosition());
                    switch (stempeluhrStatus.getStatus()) {
                        case StempeluhrStatus.WIDGET_STATUS_RUN:
                        case StempeluhrStatus.WIDGET_STATUS_PAUSE:
                            ausstempeln(
                                    stempeluhrStatus.getArbeitsplatz(),
                                    stempeluhrStatus.getBis().getAlsMinuten()
                            );
                            stempeluhrStatus.stop();
                            holder.sAbwesenheit.setSelection(0);
                            holder.close();
                            updateStempelUhr(holder.getAdapterPosition(), -1);
                            break;
                    }
                }
            });

            // Schichtauswahl bzw. Schichtname editieren
            final AdapterView.OnItemSelectedListener SchichtListSelect;
            SchichtListSelect = new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    SchichtDefault sSelect = mArbeitsplatz.getDefaultSchichten().getAktive(position);
                    if (mStempeluhr.getDefaultSchicht().getID() != sSelect.getID()) {
                        mStempeluhr.setDefaultSchicht(sSelect);
                        updateStempelUhr(holder.getAdapterPosition(), -1);
                    }
                }

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

            final View.OnLongClickListener NameLongclickListener;
            // Für den Schichtname
            NameLongclickListener = view -> {
                final InputMethodManager imm =
                        (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final EditText mInput = new EditText(mContext);
                if (mStempeluhr.getSchichtname() != null) {
                    mInput.setText(mStempeluhr.getSchichtname());
                } else if (mStempeluhr.getDefaultSchicht() != null) {
                    mInput.setText(mStempeluhr.getDefaultSchicht().getName());
                }
                mInput.setInputType(InputType.TYPE_CLASS_TEXT);
                mInput.setSelection(0, mInput.getText().length());
                mInput.setFocusableInTouchMode(true);
                mInput.requestFocus();
                //Längenbegrenzung des Inputstrings
                InputFilter[] fa = new InputFilter[1];
                fa[0] = new InputFilter.LengthFilter(ISettings.LAENGE_NAME);
                mInput.setFilters(fa);
                new AlertDialog.Builder(mContext)
                        .setTitle(mContext.getString(R.string.schichtname))
                        .setView(mInput)
                        .setPositiveButton(
                                mContext.getString(android.R.string.ok), (dialog, whichButton) -> {
                                    if (whichButton == Dialog.BUTTON_POSITIVE) {
                                        mStempeluhr.setSchichtname(mInput.getText().toString());
                                        mStempeluhr.setDefaultSchicht(null);
                                        updateStempelUhr(holder.getAdapterPosition(), -1);
                                        if (imm != null) {
                                            imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                                        }
                                    }
                                }).setNegativeButton(mContext.getString(
                                android.R.string.cancel), (dialog, whichButton) -> {
                            // Abbruchknopf gedrückt
                            if (imm != null) {
                                imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                            }

                        }).show();
                if (imm != null) {
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }

                return true;
            };


            //Klickhandler für Schichtauswahl/Schgichtname registrieren
            if (
                    mStempeluhr.getArbeitsplatz().getAnzahlSchichten() <= 1 ||
                            mStempeluhr.getSchichtname() != null
            ) {
                holder.sSchichtauswahl.setVisibility(View.GONE);
                holder.wSchichtname.setVisibility(View.VISIBLE);
                holder.wSchichtname.setOnLongClickListener(NameLongclickListener);
            } else {
                holder.sSchichtauswahl.setVisibility(View.VISIBLE);
                holder.wSchichtname.setVisibility(View.GONE);
                ArrayAdapter<String> schichtauswahlArrayAdapter = new ArrayAdapter<>(
                        mContext,
                        android.R.layout.simple_spinner_dropdown_item,
                        mArbeitsplatz.getDefaultSchichten().getAktiveNamen()
                );
                holder.sSchichtauswahl.setAdapter(schichtauswahlArrayAdapter);
                holder.sSchichtauswahl.setSelection(
                        mArbeitsplatz.getDefaultSchichten()
                                .getAktiveIndex(mStempeluhr.getDefaultSchicht().getID())
                );
                holder.sSchichtauswahl.setOnItemSelectedListener(SchichtListSelect);
                holder.sSchichtauswahl.setOnLongClickListener(NameLongclickListener);
            }

            //Klickhandler für Zahlenwerte registrieren
            holder.wVon.setOnClickListener(v -> mClickListener.onStempeluhrOpenPicker(
                    getItem(position),
                    Arbeitsschicht.WERT_VON
                    ));
            holder.wBis.setOnClickListener(v -> mClickListener.onStempeluhrOpenPicker(
                    getItem(position),
                    Arbeitsschicht.WERT_BIS
            ));
            holder.wPause.setOnClickListener(v -> mClickListener.onStempeluhrOpenPicker(
                    getItem(position),
                    Arbeitsschicht.WERT_PAUSE
            ));


            // die Kopfzeile der Uhr beschriften
            updateStempelUhr(position, -1);

            // die Uhr des Arbeitsplatzes öffnen wenn die Uhr läuft
            if (mStempeluhr.getStatus() == WidgetStatus.WIDGET_STATUS_NEU) {
                holder.close();
            } else {
                holder.open();
            }
        }
    }


    protected void ausstempeln(Arbeitsplatz arbeitsplatz, int stopZeit) {
        StempeluhrStatus stempeluhr = new StempeluhrStatus(arbeitsplatz, 0);

        if (stopZeit != stempeluhr.getVon().getAlsMinuten()) {
            // den betreffenden Arbeitstag aus der Datenbank lesen oder einen neuen anlegen
            Arbeitstag mTag = new Arbeitstag(
                    stempeluhr.getTag().getCalendar(),
                    stempeluhr.getArbeitsplatz(),
                    stempeluhr.getArbeitsplatz().getSollstundenTag(stempeluhr.getTag()),
                    stempeluhr.getArbeitsplatz().getSollstundenTagPauschal(
                            stempeluhr.getTag().get(Calendar.YEAR), stempeluhr.getTag().get(Calendar.MONTH)
                    )
            );

            // die Schicht finden, die überschrieben werden soll
            Arbeitsschicht aSchicht = null;
            // ist eine der Schichtvorlagen gewählt?
            if (stempeluhr.getDefaultSchicht() != null) {
                // wenn Teilschichten, dann in der Liste der Schichten die gewünschte suchen
                if (stempeluhr.getArbeitsplatz().isTeilschicht()) {
                    for (Arbeitsschicht s : mTag.getSchichten()) {
                        if (s.getDefaultSchichtId() == stempeluhr.getDefaultSchicht().getID()) {
                            aSchicht = s;
                            break;
                        }
                    }
                } else {
                    // im Wechselschichtmodus immer die erste Schicht überschreiben
                    aSchicht = mTag.getSchicht(0);
                    aSchicht.setDefaultSchicht(stempeluhr.getDefaultSchicht());
                }
            }

            if (aSchicht == null) {
                //es wurde keine Schicht gefunden, also eine leere anhängen
                aSchicht = new Arbeitsschicht(
                        mTag.getSchichtAnzahl(),
                        stempeluhr.getArbeitsplatz(),
                        mTag.getTagId(),
                        //(byte) mTag.getWochentag(),
                        stempeluhr.getSchichtname(),
                        stempeluhr.getTag(),
                        mTag.getTagSollBrutto(),
                        stempeluhr.getArbeitsplatz().getSollstundenTagPauschal()
                );

                aSchicht.setDefaultSchicht(stempeluhr.getDefaultSchicht());
                mTag.getSchichten().add(aSchicht);

                eintragen(stempeluhr, mTag, aSchicht, stopZeit);
            } else {
                if (aSchicht.getAbwesenheit().getKategorie() != Abwesenheit.KAT_KEINESCHICHT) {
                    final Arbeitsschicht schicht = aSchicht;
                    // die gefundene Schicht ist nicht leer
                    new AlertDialog.Builder(mContext)
                            .setTitle(mContext.getString(R.string.schicht_ersetzen))
                            .setMessage(mContext.getString(R.string.schicht_ersetzen))
                            .setNegativeButton(mContext.getString(R.string.extraschicht), (dialog, whichButton) -> {
                                // neue Schicht anlegen
                                Arbeitsschicht neueSchicht = new Arbeitsschicht(
                                        mTag.getSchichtAnzahl(),
                                        stempeluhr.getArbeitsplatz(),
                                        mTag.getTagId(),
                                        //(byte) mTag.getWochentag(),
                                        stempeluhr.getSchichtname(),
                                        stempeluhr.getTag(),
                                        mTag.getTagSollBrutto(),
                                        stempeluhr.getArbeitsplatz().getSollstundenTagPauschal()
                                );

                                neueSchicht.setDefaultSchicht(stempeluhr.getDefaultSchicht());
                                mTag.getSchichten().add(neueSchicht);

                                eintragen(stempeluhr, mTag, neueSchicht, stopZeit);
                            })
                            .setPositiveButton(mContext.getString(R.string.ueberschreiben), (dialog, whichButton) -> {
                                // eiungetragene Zeiten überschreiben
                                eintragen(stempeluhr, mTag, schicht, stopZeit);
                            }).show();
                } else {
                    eintragen(stempeluhr, mTag, aSchicht, stopZeit);
                }
            }
        } else {
            // Meldung ausgeben
            String mMeldung = ASettings.res.getString(R.string.widget_add_no_schicht);
            Toast toast = Toast.makeText(mContext, mMeldung, Toast.LENGTH_LONG);
            toast.show();
        }
    }

     private void eintragen(
             StempeluhrStatus stempeluhr,
             Arbeitstag tag,
             Arbeitsschicht schicht,
             int stopZeit
     ){
        schicht.setAll(
                stempeluhr.getAbwesenheit(),
                stempeluhr.getVon().getAlsMinuten(),
                stopZeit,
                stempeluhr.getPause().getAlsMinuten(),
                stempeluhr.getDefaultSchicht(),
                null
        );

        schicht.setEinsatzort(stempeluhr.getEinsatzort());
        schicht.getZusatzfelder(IZusatzfeld.TEXT_VOLL).setListenWerte(stempeluhr.getZusatzwertListe());
        schicht.speichern();

        // den betreffenden Monat aktuallisieren
       Arbeitsmonat mMonat = new Arbeitsmonat(
               stempeluhr.getArbeitsplatz(),
               tag.getKalender().get(Calendar.YEAR),
               tag.getKalender().get(Calendar.MONTH),
               true,
               true);
       mMonat.updateSaldo(true);

       // Meldung ausgeben
       String mMeldung = ASettings.res.getString(R.string.widget_add_schicht);
       Toast toast = Toast.makeText(mContext, mMeldung, Toast.LENGTH_LONG);
       toast.show();

       // den gestempelten Tag öffnen
           Intent mMainIntent = new Intent();
           mMainIntent.setClass(mContext, MainActivity.class);
           mMainIntent.putExtra(ISettings.KEY_ANZEIGE_VIEW, ISettings.VIEW_TAG);
           mMainIntent.putExtra(ISettings.KEY_ANZEIGE_DATUM, tag.getKalender().getTimeInMillis());
           mMainIntent.putExtra(ISettings.KEY_JOBID, stempeluhr.getArbeitsplatz().getId());
           mMainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
           mMainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
           mContext.startActivity(mMainIntent);
    }

    void updateStempelUhr(int holderPosition, int positionZusatzwert) {
        StempeluhrStatus stempeluhr = getItem(holderPosition);
        if(!mHolderList.isEmpty()) {
            StempeluhrExpandListAdapter.ViewHolder holder = mHolderList.get(holderPosition);
            switch (stempeluhr.getStatus()) {
                case StempeluhrStatus.WIDGET_STATUS_RUN:
                    holder.iStop.setVisibility(View.VISIBLE);
                    holder.iStartPause.setImageResource(R.drawable.pause);
                    updateStempeluhrWerte(holder, stempeluhr, positionZusatzwert);
                    break;
                case StempeluhrStatus.WIDGET_STATUS_PAUSE:
                    stempeluhr.updatePause(new Uhrzeit().getAlsMinuten());
                    holder.iStop.setVisibility(View.VISIBLE);
                    holder.iStartPause.setImageResource(R.drawable.start);
                    updateStempeluhrWerte(holder, stempeluhr, positionZusatzwert);
                    break;
                default:
                    holder.iStop.setVisibility(View.INVISIBLE);
                    holder.iStartPause.setImageResource(R.drawable.start);
                    break;
            }
            holder.wPausezeit.setText(stempeluhr.getPause().getStundenString(true, stempeluhr.isDezimal()));
            holder.wStempelzeit.setText(stempeluhr.getStempelzeit().getStundenString(true, stempeluhr.isDezimal()));
            holder.iStempelzeit.setImageResource(stempeluhr.getAbwesenheit().getIcon_Id());
        }
    }

    private void updateStempeluhrWerte(ViewHolder holder, StempeluhrStatus stempeluhr, int positionZusatzwert) {
        if (stempeluhr != null) {
            // Werte eintragen
            if (stempeluhr.getSchichtname() != null) {
                holder.wSchichtname.setText(stempeluhr.getSchichtname());
            }
            holder.wVon.setText(stempeluhr.getVon().getUhrzeitString());
            holder.wBis.setText(stempeluhr.getBis().getUhrzeitString());
            holder.wPause.setText(stempeluhr.getPause()
                    .getStundenString(true, stempeluhr.isDezimal())
            );

            // den Optionelen Wert Einsatzort ein- oder ausblenden
            if (stempeluhr.isEinsatzort()) {
                holder.wEinsatzort.setText(stempeluhr.getEinsatzortName());
            }

            // die Zusatzwerte ein- oder ausblenden
            if (stempeluhr.isZusatzwerte() && positionZusatzwert >= 0) {
                ZusatzWertViewAdapter viewAdapter
                        = (ZusatzWertViewAdapter)holder.gZusatzwerte.getAdapter();
                if (viewAdapter != null) {
                    viewAdapter.notifyItemChanged(positionZusatzwert);
                }
            }
        }
    }

    void aktion(long stempeluhrId, String aktion){
        int position = 0;
        for (StempeluhrStatus stempeluhr : mStempeluhren ) {
            if (stempeluhrId == stempeluhr.getId()){
                if(aktion.equals(StempeluhrStatus.START_PAUSE_CLICKED)){
                    switch (stempeluhr.getStatus()) {
                        case StempeluhrStatus.WIDGET_STATUS_NEU:
                            stempeluhr.start();
                            break;
                        case StempeluhrStatus.WIDGET_STATUS_PAUSE:
                            stempeluhr.stopPause();
                            break;
                        case StempeluhrStatus.WIDGET_STATUS_RUN:
                            stempeluhr.startPause();
                            break;
                    }
                    updateStempelUhr(position, -1);
                    //notifyItemChanged(position);
                } else if (aktion.equals(StempeluhrStatus.STOP_CLICKED)){
                    switch (stempeluhr.getStatus()) {
                        case StempeluhrStatus.WIDGET_STATUS_RUN:
                        case StempeluhrStatus.WIDGET_STATUS_PAUSE:
                            ausstempeln(
                                    stempeluhr.getArbeitsplatz(),
                                    stempeluhr.getBis().getAlsMinuten()
                            );
                            stempeluhr.stop();
                            updateStempelUhr(position, -1);
                            //notifyItemChanged(position);
                            break;
                    }
                }
                break;
            }
            position ++;
        }
    }

    @Override
    public int getItemCount() {
        if (mStempeluhren != null) {
            return mStempeluhren.size();
        } else {
            return 0;
        }
    }

    StempeluhrStatus getItem(int index) {
        if (index < getItemCount()) {
            return mStempeluhren.get(index);
        }
        return null;
    }

    // die aufrufende Activity muss diese Listener impelmentieren
    public interface ItemClickListener {
        /**
         * Aufgerufen wenn sich Werte der Schicht geändert haben
         */
        void onExpand(int position);

        // wenn ein Picker geöffnet werden soll
        void onStempeluhrOpenPicker(StempeluhrStatus status, int wert);

        void onZusatzfeldOpenPicker(StempeluhrStatus status, IZusatzfeld feld, int wert);
    }

    public class ViewHolder
            extends RecyclerView.ViewHolder
            implements
            ZusatzWertViewAdapter.ItemClickListener {
        LinearLayout bAll;
        RelativeLayout bTitel;
        TextView mTitel;
        ImageView iArrow;
        ImageView iStartPause;
        ImageView iStop;
        TextView wStempelzeit;
        TextView wPausezeit;
        ImageView iStempelzeit;
        LinearLayout bSchichtauswahl;
        TextView wSchichtname;
        Spinner sAbwesenheit;
        Spinner sSchichtauswahl;
        RelativeLayout bWerte;
        TextView wVon;
        TextView wBis;
        TextView wPause;
        LinearLayout bEinsatzort;
        TextView wEinsatzort;
        RecyclerView gZusatzwerte;
        EinsatzortAuswahlDialog eortAuswahl;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            bAll = itemView.findViewById(R.id.SU_box_all);
            bTitel = itemView.findViewById(R.id.SU_kopf_frame);
            mTitel = itemView.findViewById(R.id.SU_name_kopf);
            iArrow = itemView.findViewById(R.id.SU_arrow);
            iStartPause = itemView.findViewById(R.id.SU_button_start_pause);
            iStop = itemView.findViewById(R.id.SU_button_stop);
            iStempelzeit = itemView.findViewById(R.id.SU_icon_stempelzeit);
            wStempelzeit = itemView.findViewById(R.id.SU_wert_stempelzeit);
            wPausezeit = itemView.findViewById(R.id.SU_wert_pausezeit);

            bSchichtauswahl = itemView.findViewById(R.id.SU_box_titel);
            wSchichtname = itemView.findViewById(R.id.SU_wert_schicht);
            sSchichtauswahl = itemView.findViewById(R.id.SU_spinner_schicht);
            sAbwesenheit = itemView.findViewById(R.id.SU_spinner_abwesenheit);

            bWerte = itemView.findViewById(R.id.SU_box_werte);
            wVon = itemView.findViewById(R.id.SU_wert_von);
            wBis = itemView.findViewById(R.id.SU_wert_bis);
            wPause = itemView.findViewById(R.id.SU_wert_pause);
            bEinsatzort = itemView.findViewById(R.id.SU_box_eort);
            wEinsatzort = itemView.findViewById(R.id.SU_wert_eort);
            gZusatzwerte = itemView.findViewById(R.id.SU_grid_werte);

            if (mClickListener != null) {
                bTitel.setOnClickListener(v -> toggle());
            }
        }

        private void toggle() {
            if (mClickListener != null) {
                if (bWerte.getVisibility() == View.VISIBLE) {
                    close();
                } else {
                    open();
                }
            }
        }

        private void open(){
            StempeluhrStatus mStempeluhr = mStempeluhren.get(getAdapterPosition());
            if (mStempeluhr.getStatus() != WidgetStatus.WIDGET_STATUS_NEU) {
                bSchichtauswahl.setVisibility(View.VISIBLE);
                bWerte.setVisibility(View.VISIBLE);
                iArrow.setImageResource(R.drawable.arrow_up);

                updateStempeluhrWerte(this, mStempeluhr, -1);
                mClickListener.onExpand(getAdapterPosition());
            }
        }

        private void close(){
            bSchichtauswahl.setVisibility(View.GONE);
            bWerte.setVisibility(View.GONE);
            iArrow.setImageResource(R.drawable.arrow_down);
        }


        @Override
        public void onItemClick(View view, IZusatzfeld feld) {
            switch (feld.getDatenTyp()) {
                case IZusatzfeld.TYP_TEXT:
                    onTextClick(
                            mStempeluhren.get(getAdapterPosition()),
                            (TextView) view,
                            (Textfeld) feld
                    );
                    break;
                case IZusatzfeld.TYP_ZAHL:
                    mClickListener.onZusatzfeldOpenPicker(
                            mStempeluhren.get(getAdapterPosition()),
                            feld,
                            Arbeitsschicht.WERT_ZUSATZ_ZAHL
                    );
                    break;
                case IZusatzfeld.TYP_ZEIT:
                    mClickListener.onZusatzfeldOpenPicker(
                            mStempeluhren.get(getAdapterPosition()),
                            feld,
                            Arbeitsschicht.WERT_ZUSATZ_ZEIT
                    );
                    break;
                case IZusatzfeld.TYP_BEREICH_ZAHL:
                    if (view.getId() == R.id.ZW_wert_1)
                        mClickListener.onZusatzfeldOpenPicker(
                                mStempeluhren.get(getAdapterPosition()),
                                feld,
                                Arbeitsschicht.WERT_ZUSATZ_ZAHL_VON
                        );
                    else if (view.getId() == R.id.ZW_wert_2)
                        mClickListener.onZusatzfeldOpenPicker(
                                mStempeluhren.get(getAdapterPosition()),
                                feld,
                                Arbeitsschicht.WERT_ZUSATZ_ZAHL_BIS
                        );
                    break;
                case IZusatzfeld.TYP_BEREICH_ZEIT:
                    if (view.getId() == R.id.ZW_wert_1)
                        mClickListener.onZusatzfeldOpenPicker(
                                mStempeluhren.get(getAdapterPosition()),
                                feld,
                                Arbeitsschicht.WERT_ZUSATZ_ZEIT_VON
                        );
                    else if (view.getId() == R.id.ZW_wert_2)
                        mClickListener.onZusatzfeldOpenPicker(
                                mStempeluhren.get(getAdapterPosition()),
                                feld,
                                Arbeitsschicht.WERT_ZUSATZ_ZEIT_BIS
                        );
                    break;
                case IZusatzfeld.TYP_AUSWAHL_TEXT:
                case IZusatzfeld.TYP_AUSWAHL_ZAHL:
                case IZusatzfeld.TYP_AUSWAHL_ZEIT:
                case IZusatzfeld.TYP_AUSWAHL_PROZENT:
                    mClickListener.onZusatzfeldOpenPicker(
                            mStempeluhren.get(getAdapterPosition()),
                            feld,
                            Arbeitsschicht.WERT_ZUSATZ_AUSWAHL
                    );
                    break;
            }
        }

        // reagiert auf einen Zusatzeintrag in Textform
        private void onTextClick(StempeluhrStatus status, final TextView view, final Textfeld feld) {
            final InputMethodManager imm =
                    (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
            final AutoCompleteTextView mInput = new AutoCompleteTextView(mContext);
            mInput.setText(feld.getStringWert(false));
            mInput.setSelection(0, feld.getStringWert(false).length());
            mInput.setFocusableInTouchMode(true);
            mInput.setInputType(
                    InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                            | InputType.TYPE_CLASS_TEXT
                            | InputType.TYPE_TEXT_FLAG_MULTI_LINE
            );

            TextFeldTextListe textListe = new TextFeldTextListe(feld.getDefinitionID());
            ArrayAdapter<String> adapter = new ArrayAdapter<>(
                    mContext, android.R.layout.simple_list_item_1, textListe.getArray()
            );
            mInput.setAdapter(adapter);

            //Längenbegrenzung des Inputstrings
            InputFilter[] fa = new InputFilter[1];
            fa[0] = new InputFilter.LengthFilter(ISettings.LAENGE_NOTIZ);
            mInput.setFilters(fa);

            new AlertDialog.Builder(mContext)
                    .setTitle(feld.getName())
                    .setView(mInput)
                    .setPositiveButton(
                            mContext.getString(android.R.string.ok),
                            (dialog, whichButton) -> {
                                if (whichButton == Dialog.BUTTON_POSITIVE) {
                                    feld.setWert(mInput.getText().toString());
                                    view.setText(mInput.getText());
                                    if (imm != null) {
                                        imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                                    }
                                    //updateStempelUhr(getAdapterPosition(), feld.getPosition());
                                    notifyItemChanged(getAdapterPosition());
                                    status.save(ASettings.mPreferenzen);
                                }
                            }).setNegativeButton(
                            mContext.getString(android.R.string.cancel),
                            (dialog, whichButton) -> {
                                // Abbruchknopf gedrückt
                                if (imm != null) {
                                    imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                                }
                            }).show();

            mInput.requestFocus();
            if (imm != null) {
                imm.toggleSoftInputFromWindow(
                        mInput.getWindowToken(),
                        InputMethodManager.SHOW_FORCED,
                        0
                );
            }
        }


    }
}
