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

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
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.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.appcompat.widget.AppCompatRadioButton;
import androidx.appcompat.widget.AppCompatSpinner;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.view.ViewCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Locale;

import askanimus.arbeitszeiterfassung2.Datum;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.StorageHelper;
import askanimus.arbeitszeiterfassung2.Zeitraum.Zeitraum_Monat;
import askanimus.arbeitszeiterfassung2.arbeitsmonat.Arbeitsmonat;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.betterpickers.expirationpicker.ExpirationPickerBuilder;
import askanimus.betterpickers.expirationpicker.ExpirationPickerDialogFragment;
import askanimus.betterpickers.numberpicker.NumberPickerBuilder;
import askanimus.betterpickers.numberpicker.NumberPickerDialogFragment;

/**
 * @author askanimus@gmail.com on 09.01.16.
 */
public class Export_Fragment_Monat 
        extends Fragment
        implements
        IExport_Fragment,
        View.OnClickListener,
        AppCompatCheckBox.OnCheckedChangeListener,
        RadioGroup.OnCheckedChangeListener,
        ExpirationPickerDialogFragment.ExpirationPickerDialogHandler,
        Fragment_Dialog_Spalten.EditSpaltenDialogListener,
        Fragment_Dialog_Zeilen.EditZeilenDialogListener,
        NumberPickerDialogFragment.NumberPickerDialogHandlerV2,
        AdapterView.OnItemSelectedListener {

    private BitSet bsSpalten;
    private BitSet bsSpaltenDeaktiv;
    private BitSet bsOptionen;
    private BitSet bsOptionenDeaktiv;
    private BitSet bsZusatzfelder;

    private String KEY_EXPORT_SPALTEN;
    private String KEY_EXPORT_OPTIONEN;
    private String KEY_EXPORT_ZUSATZ;

    private int exportDateityp;
    
    private int exportVariante;

    private Datum kStarttag;
    private int mAnzahlMonate = 1;

    private static IExportFinishListener mCallback;
        
    private final SimpleDateFormat fMonat = new SimpleDateFormat("MMMM yyyy", Locale.getDefault());
    //private final DateFormat fBereich = DateFormat.getDateInstance(DateFormat.SHORT);

    private TextView wHintDateityp;
    private RadioGroup rgGroesse;
    private RadioGroup rgLayout;
    private TextView   hVariante;

    private LinearLayout bEinstellungen;

    private TextView wTrenner;
    private LinearLayout bTrenner;
    private TextView wMonatsname;
    private TextView wAnzahlMonate;
    private TextView wNachwort;

    private TextView wNotiz;

    private LinearLayout bOptionen;
    private LinearLayout bVarianten;

    private AppCompatCheckBox cbEortSort;

    private Context mContext;

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
   public static Export_Fragment_Monat newInstance(IExportFinishListener cb, long startdatum) {
       mCallback = cb;
        Export_Fragment_Monat fragment = new Export_Fragment_Monat();
        Bundle args = new Bundle();
        args.putLong(ISettings.ARG_DATUM, startdatum);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mContext = getContext();

        if (savedInstanceState != null) {
            setArguments(savedInstanceState);
        }


        return inflater.inflate(R.layout.fragment_export_monat, container, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        ASettings.init(mContext, this::resume);
    }

    private void resume() {
        Bundle mArgs = getArguments();

        if (mArgs != null) {
            kStarttag = new Datum(mArgs.getLong(ISettings.ARG_DATUM), ASettings.aktJob.getWochenbeginn());
            mAnzahlMonate = mArgs.getInt(ISettings.ARG_ANZAHL, 1);

            kStarttag.setTag(ASettings.aktJob.getMonatsbeginn());

            if(kStarttag.liegtNach(ASettings.letzterAnzeigeTag)){
                kStarttag.set(ASettings.letzterAnzeigeTag.getCalendar());
                kStarttag.setTag(ASettings.aktJob.getMonatsbeginn());
            }
        } /*else {
            kStarttag = new Datum(ASettings.aktDatum.getTime(), ASettings.aktJob.getWochenbeginn());
        }*/
        // der Datumsbereich
        /*Datum kEndTag = new Datum(kStarttag);
        kEndTag.add(Calendar.DAY_OF_MONTH, kStarttag.getAktuellMaximum(Calendar.DAY_OF_MONTH) - 1);
        if(kEndTag.liegtNach(ASettings.letzterAnzeigeTag)){
           kEndTag.set(ASettings.letzterAnzeigeTag.getCalendar());
        }
        String sbereich = "( " + fBereich.format(kStarttag.getTime()) + " - ";
        sbereich += fBereich.format(kEndTag.getTime()) + " )";*/

        // Oberfläche anpssen
        View rootView = getView();
        if (rootView != null) {
            // die Anzeige- un Bedienelemente finden
            bEinstellungen = rootView.findViewById(R.id.EM_pdfOptionen);
            AppCompatCheckBox cbZusammenfassung = rootView.findViewById(R.id.EM_button_zus);
            rgGroesse = rootView.findViewById(R.id.EM_gruppe_groesse);
            rgLayout = rootView.findViewById(R.id.EM_gruppe_layout);
            wTrenner = rootView.findViewById(R.id.EM_wert_trenner);
            wMonatsname = rootView.findViewById(R.id.EM_wert_monat);
            bTrenner = rootView.findViewById(R.id.EM_box_trenner);
            wNotiz = rootView.findViewById(R.id.EM_wert_notiz);
            wAnzahlMonate = rootView.findViewById(R.id.EM_wert_anzahl);
            wNachwort = rootView.findViewById(R.id.EM_nachwort);
            cbEortSort = rootView.findViewById(R.id.EM_button_sort_eort);
            bVarianten = rootView.findViewById(R.id.EM_box_varianten);
            bOptionen = rootView.findViewById(R.id.EM_box_auswahl);
            hVariante = rootView.findViewById(R.id.EM_hint_varianten);
            RadioGroup rgVariante = rootView.findViewById(R.id.EM_gruppe_varianten);
            RadioGroup rgDateityp = rootView.findViewById(R.id.EM_gruppe_typ);
            wHintDateityp = rootView.findViewById(R.id.EM_hint_dateityp);
            ImageButton ibEditSpalten = rootView.findViewById(R.id.EM_button_edit_spalten);
            ImageButton ibEditZeilen = rootView.findViewById(R.id.EM_button_edit_zeilen);
            AppCompatSpinner spinnerFontSize = rootView.findViewById(R.id.EM_spinner_fontgroesse);

            wMonatsname.setText(fMonat.format(kStarttag.getDate()));
            updateAnzahlMonate(mAnzahlMonate);

            // Voreinstellungen an Hand der letzten Auswahl laden
            // bis zur Version 10291 war für alle Exporte nur ein gemeinsamer Dateityp gespeichert
            exportDateityp = ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_TYP_MONAT, ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_TYP, IExport_Basis.TYP_PDF));
            exportVariante = ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_M_VARIANTE, IExport_Basis.AUSFUERLICH);

            long i = ASettings.aktJob.getId();
            switch (exportVariante) {
                case IExport_Basis.LGAV:
                    KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_LGAV + i;
                    KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_LGAV + i;
                    KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_LGAV + i;
                    break;
                case IExport_Basis.VERKUERZT:
                    KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_KURZ + i;
                    KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_KURZ + i;
                    KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_KURZ + i;
                    break;
                default:
                    KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_AUSF + i;
                    KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_AUSF + i;
                    KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_AUSF + i;
            }

            // Farben der Knöpfe anpassen
            // Radiobutton
            for (View v : rgDateityp.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            for (View v : rgGroesse.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            for (View v : rgLayout.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            for (View v : rgVariante.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            // Checkboxen
            CompoundButtonCompat.setButtonTintList(
                    cbZusammenfassung,
                    ASettings.aktJob.getFarbe_Radio());
            CompoundButtonCompat.setButtonTintList(
                    cbEortSort,
                    ASettings.aktJob.getFarbe_Radio());

            // Spalte- und Zeilenknöpfe
            ViewCompat.setBackgroundTintList(ibEditSpalten, ASettings.aktJob.getFarbe_Button());
            ViewCompat.setBackgroundTintList(ibEditZeilen, ASettings.aktJob.getFarbe_Button());

            // Handler registrieren
            cbZusammenfassung.setOnCheckedChangeListener(this);
            rgGroesse.setOnCheckedChangeListener(this);
            rgLayout.setOnCheckedChangeListener(this);
            wTrenner.setOnClickListener(this);
            wMonatsname.setOnClickListener(this);
            wAnzahlMonate.setOnClickListener(this);
            wNotiz.setOnClickListener(this);
            ibEditSpalten.setOnClickListener(this);
            ibEditZeilen.setOnClickListener(this);
            cbEortSort.setOnCheckedChangeListener(this);
            rgDateityp.setOnCheckedChangeListener(this);
            rgVariante.setOnCheckedChangeListener(this);
            spinnerFontSize.setOnItemSelectedListener(this);

            // Werte an Hand der letzten Auswahl vorbelegen
            // die Auswahl des Dateityps
            int d = exportDateityp;
            rgDateityp.clearCheck();
            switch (d) {
                case IExport_Basis.TYP_CSV:
                    rgDateityp.check(R.id.EM_button_csv);
                    break;
                case IExport_Basis.TYP_CAL_CSV:
                    rgDateityp.check(R.id.EM_button_cal);
                    break;
                case IExport_Basis.TYP_CAL_ICS:
                    rgDateityp.check(R.id.EM_button_ics);
                    break;
                default:
                    rgDateityp.check(R.id.EM_button_pdf);
                    break;
            }

            // die Auswahl der Berichtsvariante
            d = exportVariante;
            rgVariante.clearCheck();
            switch (d) {
                case IExport_Basis.LGAV:
                    rgVariante.check(R.id.EM_button_lgav);
                    break;
                case IExport_Basis.VERKUERZT:
                    rgVariante.check(R.id.EM_button_kurz);
                    break;
                default:
                    rgVariante.check(R.id.EM_button_ausf);
            }

            // die Liste der Spalten
            // die Bitsets für Spalten, Zeilen/Optionen und Zusatzwerte initialisieren
            bsSpalten = new BitSet(IExport_Basis.DEF_MAXBIT_SPALTE);
            bsOptionen = new BitSet(IExport_Basis.DEF_MAXBIT_OPTION);
            bsSpaltenDeaktiv = new BitSet(IExport_Basis.DEF_MAXBIT_SPALTE);
            bsOptionenDeaktiv = new BitSet(IExport_Basis.DEF_MAXBIT_OPTION);
            bsZusatzfelder = new BitSet();
            initSpaltenZeilen();

            // die Monatszusammenfassung
            boolean b = bsOptionen.get(IExport_Basis.OPTION_ZUSAMMENFASSUNG);
            cbZusammenfassung.setChecked(false);
            cbZusammenfassung.setChecked(b);

            // die Zusatztabelle nach Einsatzorten sortiert
            b = bsOptionen.get(IExport_Basis.OPTION_ZUSATZTABELLE_EORT);
            cbEortSort.setChecked(false);
            cbEortSort.setChecked(b);

            // die Seitengrösse
            b = bsOptionen.get(IExport_Basis.OPTION_LAYOUT_A3);
            rgGroesse.clearCheck();
            rgGroesse.check(b ? R.id.EM_button_a3 : R.id.EM_button_a4);

            // das Seitenlayout
            b = bsOptionen.get(IExport_Basis.OPTION_LAYOUT_QUEER);
            rgLayout.clearCheck();
            rgLayout.check(b ? R.id.EM_button_quer : R.id.EM_button_hoch);
            // Werte an Hand der letzten Auswahl vorbelegen
            // das Trennzeichen für den CSV export
            wTrenner.setText(ASettings.mPreferenzen.getString(ISettings.KEY_EXPORT_CSV_TRENNER, ";"));


            // Notiz, die auf dem Wochenreport gedruckt wird
            wNotiz.setText(ASettings.mPreferenzen.getString(ISettings.KEY_EXP_M_NOTIZ, ""));

            // die Vorauswahl der Schriftgrösse
            spinnerFontSize.setSelection(ASettings.mPreferenzen.getInt(
                    ISettings.KEY_EXP_M_FONTSIZE, IExport_Basis.MIN_FONTSIZE
            ));

        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        if(kStarttag != null) {
            outState.putLong(ISettings.ARG_DATUM, kStarttag.getTimeInMillis());
            outState.putInt(ISettings.ARG_ANZAHL, mAnzahlMonate);
        }
    }

    /*
     * Handlerfunktionen
     */
    @Override
    public void onClick(View v) {
        FragmentManager fManager;
        try {
            fManager = getParentFragmentManager();

            int id = v.getId();
            if (id == R.id.EM_wert_notiz) {
                final InputMethodManager immNotiz = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final AlertDialog.Builder mDialogNotiz = new AlertDialog.Builder(mContext);
                final EditText mInputNotiz = new EditText(getActivity());
                mInputNotiz.setText(wNotiz.getText());
                mInputNotiz.setSelection(wNotiz.getText().length());
                mInputNotiz.setFocusableInTouchMode(true);
                mInputNotiz.requestFocus();
                mInputNotiz.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
                mInputNotiz.setMaxLines(8);
                mDialogNotiz.setTitle(R.string.exp_notiz_hint);
                mDialogNotiz.setView(mInputNotiz);
                mDialogNotiz.setPositiveButton(getString(android.R.string.ok), (dialog, whichButton) -> {
                    wNotiz.setText(mInputNotiz.getText());
                    SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
                    mEdit.putString(ISettings.KEY_EXP_M_NOTIZ, wNotiz.getText().toString()).apply();
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputNotiz.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.setNegativeButton(getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputNotiz.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.show();
                if (immNotiz != null) {
                    immNotiz.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
            } else if (id == R.id.EM_wert_trenner) {
                final InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final AlertDialog.Builder mDialog = new AlertDialog.Builder(mContext);
                final EditText mInput = new EditText(getActivity());
                mInput.setText(wTrenner.getText());
                mInput.setSelection(wTrenner.getText().length());
                mInput.setMaxLines(1);
                mInput.setFocusableInTouchMode(true);
                mInput.requestFocus();
                mInput.setInputType(InputType.TYPE_CLASS_TEXT);
                mDialog.setTitle(R.string.exp_titel_trenner);
                mDialog.setView(mInput);
                mDialog.setPositiveButton(getString(android.R.string.ok), (dialog, whichButton) -> {
                    wTrenner.setText(mInput.getText());
                    SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
                    mEdit.putString(ISettings.KEY_EXPORT_CSV_TRENNER, wTrenner.getText().toString()).apply();
                    if (imm != null) {
                        imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                    }
                });
                mDialog.setNegativeButton(getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    if (imm != null) {
                        imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
                    }
                });
                mDialog.show();
                if (imm != null) {
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
            } else if (id == R.id.EM_wert_monat) {
                ExpirationPickerBuilder epb = new ExpirationPickerBuilder()
                        .setFragmentManager(fManager)
                        .setStyleResId(ASettings.themePicker)
                        .setMinDate(ASettings.aktJob.getStartDatum().get(Calendar.YEAR), ASettings.aktJob.getStartDatum().get(Calendar.MONTH)-1)
                        .setMaxDate(ASettings.letzterAnzeigeTag.get(Calendar.YEAR), ASettings.letzterAnzeigeTag.get(Calendar.MONTH)-1)
                        .setReference(R.id.EM_wert_monat)
                        .setTargetFragment(this);
                epb.show();
            }  else if (id == R.id.EM_wert_anzahl) {
                int mMaxAnzahl;
                try {
                    fManager = getParentFragmentManager();
                    mMaxAnzahl = kStarttag.monateBis(ASettings.letzterAnzeigeTag) + 1;
                    NumberPickerBuilder prozentPicker = new NumberPickerBuilder()
                            .setFragmentManager(fManager)
                            .setStyleResId(ASettings.themePicker)
                            .setMinNumber(BigDecimal.valueOf(1))
                            .setMaxNumber(BigDecimal.valueOf(mMaxAnzahl))
                            .setLabelText(getString(R.string.monate))
                            //.setCurrentNumber(anzahlJahre)
                            .setPlusMinusVisibility(View.INVISIBLE)
                            .setDecimalVisibility(View.INVISIBLE)
                            .setReference(R.id.EM_wert_anzahl)
                            .setTargetFragment(this);
                    prozentPicker.show();
                } catch (IllegalStateException ise) {
                    ise.printStackTrace();
                }
            } else if (id == R.id.EM_button_edit_spalten) {// Spaltenauswahldialog
                //if (fManager != null) {
                    Fragment_Dialog_Spalten mDialogSpalten = new Fragment_Dialog_Spalten(
                            bsSpalten, bsSpaltenDeaktiv, bsZusatzfelder, this
                    );
                    //mDialogSpalten.setup(bsSpalten, bsSpaltenDeaktiv, bsZusatzfelder, this);
                    mDialogSpalten.show(fManager, "EditSpaltenDialog");
                //}
            } else if (id == R.id.EM_button_edit_zeilen) {// Zeilenauswahldialog
                //if (fManager != null) {
                    Fragment_Dialog_Zeilen mDialogZeilen = new Fragment_Dialog_Zeilen(
                            ASettings.aktJob,
                            bsOptionen,
                            bsOptionenDeaktiv,
                            this,
                            IExport_Basis.PERIODE_MONAT);
                    /*mDialogZeilen.setup(
                            ASettings.aktJob,
                            bsOptionen,
                            bsOptionenDeaktiv,
                            this,
                            IExport_Basis.PERIODE_MONAT);*/
                    mDialogZeilen.show(fManager, "EditZeilenDialog");
                //}
            }
        } catch (IllegalStateException ignore){
        }
    }

public void onDialogNumberSet(int reference, BigInteger number, double decimal, boolean isNegative, BigDecimal fullNumber) {
        if(reference == R.id.EM_wert_anzahl) {
            updateAnzahlMonate(number.intValue());
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
        int id = group.getId();
        if (id == R.id.EM_gruppe_groesse){
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_A3, (checkedId == R.id.EM_button_a3));
            int value = 0;
            for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_OPTION; ++i) {
                value += bsOptionen.get(i) ? (1 << i) : 0;
            }
            mEdit.putInt(KEY_EXPORT_OPTIONEN, value);
        } else if (id == R.id.EM_gruppe_layout) {
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_QUEER, (checkedId == R.id.EM_button_quer));
            int value = 0;
            for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_OPTION; ++i) {
                value += bsOptionen.get(i) ? (1 << i) : 0;
            }
            mEdit.putInt(KEY_EXPORT_OPTIONEN, value);
        } else if (id == R.id.EM_gruppe_typ) {
            if (checkedId == R.id.EM_button_csv) {
                exportDateityp = IExport_Basis.TYP_CSV;

                bEinstellungen.setVisibility(View.VISIBLE);
                bTrenner.setVisibility(View.VISIBLE);
                rgGroesse.setVisibility(View.GONE);
                rgLayout.setVisibility(View.GONE);
                bOptionen.setVisibility(View.VISIBLE);
                bVarianten.setVisibility(View.GONE);
                wHintDateityp.setText(R.string.export_hint_csv);
                if (bsOptionenDeaktiv != null) {
                    bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, true);
                }
            } else if (checkedId == R.id.EM_button_cal) {
                exportDateityp = IExport_Basis.TYP_CAL_CSV;
                bEinstellungen.setVisibility(View.GONE);
                wHintDateityp.setText(R.string.export_hint_csv_cal);
            } else if (checkedId == R.id.EM_button_ics) {
                exportDateityp = IExport_Basis.TYP_CAL_ICS;
                bEinstellungen.setVisibility(View.GONE);
                wHintDateityp.setText(R.string.export_hint_ics_cal);
            } else {
                exportDateityp = IExport_Basis.TYP_PDF;

                bEinstellungen.setVisibility(View.VISIBLE);
                bTrenner.setVisibility(View.GONE);
                rgGroesse.setVisibility(View.VISIBLE);
                rgLayout.setVisibility(View.VISIBLE);
                bOptionen.setVisibility(View.VISIBLE);
                bVarianten.setVisibility(View.VISIBLE);
                wHintDateityp.setText(R.string.export_hint_pdf);
                if (bsOptionenDeaktiv != null) {
                    bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, false);
                }
            }
            mEdit.putInt(ISettings.KEY_EXP_TYP_MONAT, exportDateityp);
        } else if (id == R.id.EM_gruppe_varianten) {
            long i = ASettings.aktJob.getId();
            if (checkedId == R.id.EM_button_lgav) {
                exportVariante = IExport_Basis.LGAV;
                hVariante.setText(getString(R.string.exp_hint_lgav));
                KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_LGAV + i;
                KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_LGAV + i;
                KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_LGAV + i;
                if (bsSpalten != null) {
                    initSpaltenZeilen();
                }
            } else if (checkedId == R.id.EM_button_kurz) {
                exportVariante = IExport_Basis.VERKUERZT;
                hVariante.setText(getString(R.string.exp_hint_kurz));
                KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_KURZ + i;
                KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_KURZ + i;
                KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_KURZ + i;
                if (bsSpalten != null) {
                    initSpaltenZeilen();
                }
            } else {
                exportVariante = IExport_Basis.AUSFUERLICH;
                hVariante.setText(getString(R.string.exp_hint_ausf));
                KEY_EXPORT_SPALTEN = ISettings.KEY_EXP_M_SPALTEN_AUSF + i;
                KEY_EXPORT_OPTIONEN = ISettings.KEY_EXP_M_ZEILEN_AUSF + i;
                KEY_EXPORT_ZUSATZ = ISettings.KEY_EXP_M_ZUSATZ_AUSF + i;
                if (bsSpalten != null) {
                    initSpaltenZeilen();
                }
            }
            mEdit.putInt(ISettings.KEY_EXP_M_VARIANTE, exportVariante);
        }
        mEdit.apply();
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int id = buttonView.getId();// Optionen
        if (id == R.id.EM_button_zus) {
            bsOptionen.set(IExport_Basis.OPTION_ZUSAMMENFASSUNG, isChecked);
        } else if (id == R.id.EM_button_sort_eort) {
            bsOptionen.set(IExport_Basis.OPTION_ZUSATZTABELLE_EORT, isChecked);
        }
        SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
        int value = 0;
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_OPTION; ++i) {
            value += bsOptionen.get(i) ? (1 << i) : 0;
        }
        mEdit.putInt(KEY_EXPORT_OPTIONEN, value);

        mEdit.apply();
    }


    @Override
    public void onDialogExpirationSet(int reference, int year, int monthOfYear) {
        if (reference == R.id.EM_wert_monat) {
            Datum mDatumMin = ASettings.aktJob.getAbrechnungsmonat(ASettings.aktJob.getStartDatum());
            int mMin = mDatumMin.get(Calendar.YEAR) * 12 + mDatumMin.get(Calendar.MONTH);
            int mMax = ASettings.letzterAnzeigeTag.get(Calendar.YEAR) * 12 + ASettings.letzterAnzeigeTag.get(Calendar.MONTH);
            int mWahl = year * 12 + monthOfYear;
            if (mWahl < mMin) {
                Toast.makeText(mContext, R.string.datum_vor_beginn, Toast.LENGTH_LONG).show();
                year = mDatumMin.get(Calendar.YEAR);
                monthOfYear = mDatumMin.get(Calendar.MONTH);
            } else if (ASettings.aktJob.isSetEnde() && (mMax < mWahl)) {
                Toast.makeText(mContext, R.string.datum_nach_ende, Toast.LENGTH_LONG).show();
                year = ASettings.letzterAnzeigeTag.get(Calendar.YEAR);
                monthOfYear = ASettings.letzterAnzeigeTag.get(Calendar.MONTH);
            }
            kStarttag.setJahr(year);
            kStarttag.setMonat(monthOfYear);
            wMonatsname.setText(fMonat.format(kStarttag.getDate()));

            //Den Datumsbereich setzten
            /*Datum kEndTag = new Datum(kStarttag.getTimeInMillis(), ASettings.aktJob.getWochenbeginn());
            kEndTag.add(Calendar.DAY_OF_MONTH, kStarttag.getAktuellMaximum(Calendar.DAY_OF_MONTH) - 1);
            String sbereich = "( " + fBereich.format(kStarttag.getTime()) + " - ";
            sbereich += fBereich.format(kEndTag.getTime()) + " )";
            wMonatsbereich.setText(sbereich);*/

            updateAnzahlMonate(mAnzahlMonate);
        }
    }

    // die ausgewählte Schriftgrösse übernehmen
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        ASettings.mPreferenzen.edit().putInt(ISettings.KEY_EXP_M_FONTSIZE, position).apply();
    }

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


    //
    // die Bitsets für Spalten und Zeilen initialisieren
    //
    private void initSpaltenZeilen(){
        int mWert =  ASettings.mPreferenzen.getInt(KEY_EXPORT_SPALTEN, IExport_Basis.DEF_SPALTEN);
        // die Spalten
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_SPALTE; i++) {
            bsSpalten.set(i, (mWert & (1 << i)) != 0);
        }

        // die deaktivierten Spalten
        bsSpaltenDeaktiv.clear();//set(0, IExport_Basis.DEF_MAXBIT_SPALTE, false);

        // die daktivierten Zeilen
        bsOptionenDeaktiv.clear();//set(0, IExport_Basis.DEF_MAXBIT_OPTION, false);

        // ist kein Stundenlohn hinterlegt, dann die Spalte deaktivieren
        if(ASettings.aktJob.getStundenlohn() == 0) {
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_VERDIENST, true);
            bsSpalten.set(IExport_Basis.SPALTE_VERDIENST, false);
        }
        // werden keine Einsatzorte erfasst,
        // dann die entsprechenden Spalten und Optionen deaktivieren
        if (!ASettings.aktJob.isOptionSet(Arbeitsplatz.OPT_WERT_EORT)) {
            // es werden keine Einsatzorte erfasst
            // also werden entsprechende Option deaktiviert
            cbEortSort.setVisibility(View.GONE);
            bsSpalten.set(IExport_Basis.SPALTE_EORT, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_EORT, true);
        }

        // Spaltenset für den Bericht nach LGAV anpassen
        if(exportVariante == IExport_Basis.LGAV) {
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_VON, true);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_BIS, true);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_BRUTTO, true);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_PAUSE, true);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_NETTO, true);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_TAGSOLL, true);
            bsSpalten.set(IExport_Basis.SPALTE_TAGSOLL, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_TAGSALDO, true);
            bsSpalten.set(IExport_Basis.SPALTE_TAGSALDO, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_SCHICHTNAME, true);
            bsSpalten.set(IExport_Basis.SPALTE_SCHICHTNAME, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_ANGELEGT, true);
            bsSpalten.set(IExport_Basis.SPALTE_ANGELEGT, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_AENDERUNG, true);
            bsSpalten.set(IExport_Basis.SPALTE_AENDERUNG, false);

            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_SUMMETAG, true);
            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_SUMMEZEITRAUM, true);
            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_SALDOZEITRAUM, true);
            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_SOLLZEITRAUM, true);
        }

        // Spaltenset für den Bericht "Kurz" anpassen
        if(exportVariante == IExport_Basis.VERKUERZT) {
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_VON, true);
            bsSpalten.set(IExport_Basis.SPALTE_VON, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_BIS, true);
            bsSpalten.set(IExport_Basis.SPALTE_BIS, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_EORT, true);
            bsSpalten.set(IExport_Basis.SPALTE_EORT, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_ANGELEGT, true);
            bsSpalten.set(IExport_Basis.SPALTE_ANGELEGT, false);
            bsSpaltenDeaktiv.set(IExport_Basis.SPALTE_AENDERUNG, true);
            bsSpalten.set(IExport_Basis.SPALTE_AENDERUNG, false);

            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_SUMMETAG, true);
        }


        // die Zusatzwerte
        mWert = ASettings.mPreferenzen.getInt(KEY_EXPORT_ZUSATZ, 0b0);
        for (int i = 0; i < ASettings.aktJob.getZusatzfeldListe().size(); i++) {
            bsZusatzfelder.set(i, (mWert & (1 << i)) != 0);
        }

        // die Zeilen und Optionen
        mWert = ASettings.mPreferenzen.getInt(KEY_EXPORT_OPTIONEN, IExport_Basis.DEF_OPTIONEN);
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_OPTION; i++) {
            bsOptionen.set(i, (mWert & (1 << i)) != 0);
        }

        // diese Option wird derzeit noch nicht benutzt
        bsOptionen.set(IExport_Basis.OPTION_ALL_JOBS, false);

        // in allen Dateien, ausser PDFs die Unterschriften deaktivieren
        if (exportDateityp != IExport_Basis.TYP_PDF) {
            bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, true);
        }
    }

    @Override
    public void onEditSpaltenPositiveClick(BitSet spalten, BitSet zusatzwerte) {
        int value;

        if(!bsSpalten.equals(spalten)) {
            bsSpalten = (BitSet) spalten.clone();
            value = 0;
            for (int i = 0; i < bsSpalten.size(); ++i) {
                value += bsSpalten.get(i) ? (1 << i) : 0;
            }
            ASettings.mPreferenzen.edit().putInt(KEY_EXPORT_SPALTEN, value).apply();
        }

        if(!bsZusatzfelder.equals(zusatzwerte)) {
            bsZusatzfelder = (BitSet) zusatzwerte.clone();
            value = 0;
            for (int i = 0; i < bsZusatzfelder.size(); ++i) {
                value += bsZusatzfelder.get(i) ? (1 << i) : 0;
            }
            ASettings.mPreferenzen.edit().putInt(KEY_EXPORT_ZUSATZ, value).apply();
        }
    }

    @Override
    public void onEditZeilenPositiveClick(BitSet zeilen, String unetrschriftAG, String unterschriftAN) {
        if(!zeilen.equals(bsOptionen)){
            bsOptionen = (BitSet) zeilen.clone();
            int value = 0;
            for (int i = 0; i < bsOptionen.size(); ++i) {
                value += bsOptionen.get(i) ? (1 << i) : 0;
            }
            ASettings.mPreferenzen.edit().putInt(KEY_EXPORT_OPTIONEN, value).apply();
        }
        ASettings.aktJob.setUnterschrift_AG(unetrschriftAG);
        ASettings.aktJob.setUnterschrift_AN(unterschriftAN);
        ASettings.aktJob.schreibeJob();
    }

    // wird von der Aktivity aufgerufen, um den Export anzustossen sowie die Weiterleitung(Mail etc.) zu atrrangieren
    public void action(int action, Arbeitsplatz job, StorageHelper storageHelper){
        if(kStarttag != null) {
            exportSave(action, job, storageHelper);
        }
    }


    /*
     * Arbeitstask zum erzeugen und speichern des Berichtes
     */
    private void exportSave(final int action, Arbeitsplatz job, final StorageHelper storageHelper) {
        ProgressDialog mDialog;

        Handler mHandler = new Handler();
        // Fortschritsdialog öffnen
        mDialog = new ProgressDialog(mContext);
        mDialog.setIndeterminate(true);
        mDialog.setIndeterminateDrawable(
                ResourcesCompat.getDrawable(
                        getResources(),
                        R.drawable.progress_dialog_anim,
                        requireActivity().getTheme()
                )
        );
        mDialog.setMessage(getString(R.string.progress_export));
        mDialog.setCancelable(false);
        mDialog.show();

        new Thread(() -> {
            Datum berichtMonat = new Datum(kStarttag);
            boolean mStatus = true;
            ArrayList<String> mDateinamen = new ArrayList<String>();
            Zeitraum_Monat mMonat;

            for (int i = 0; i < mAnzahlMonate; i++) {
                mMonat = new Zeitraum_Monat(
                        new Arbeitsmonat(
                                job,
                                berichtMonat.get(Calendar.YEAR),
                                berichtMonat.get(Calendar.MONTH),
                                true,
                                false
                        )
                );
                switch (exportDateityp) {
                    case IExport_Basis.TYP_CAL_ICS:
                        Export_ICS mICSMonat;
                        try {
                            mICSMonat = new Export_ICS(
                                    mContext,
                                    mMonat,
                                    bsOptionen,
                                    storageHelper
                            );
                            mDateinamen.add(mICSMonat.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    case IExport_Basis.TYP_CSV:
                        Export_CSV_Zeitraum mCSVMonat;
                        try {
                            mCSVMonat = new Export_CSV_Zeitraum(
                                    mContext,
                                    mMonat,
                                    bsSpalten,
                                    bsOptionen,
                                    bsZusatzfelder,
                                    storageHelper
                            );
                            mDateinamen.add(mCSVMonat.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    case IExport_Basis.TYP_CAL_CSV:
                        Export_CAL mCALMonat;
                        try {
                            mCALMonat = new Export_CAL(
                                    mContext,
                                    mMonat,
                                    bsOptionen,
                                    storageHelper
                            );
                            mDateinamen.add(mCALMonat.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    default:
                        exportDateityp = IExport_Basis.TYP_PDF;
                        switch (exportVariante) {
                            case IExport_Basis.VERKUERZT:
                                bsSpalten.set(IExport_Basis.SPALTE_VON, false);
                                bsSpalten.set(IExport_Basis.SPALTE_BIS, false);
                                bsSpalten.set(IExport_Basis.SPALTE_EORT, false);
                                Export_PDF_Zeitraum_Kurz pdf_monat_kurz;
                                try {
                                    pdf_monat_kurz = new Export_PDF_Zeitraum_Kurz(
                                            mContext,
                                            mMonat,
                                            bsSpalten,
                                            bsOptionen,
                                            bsZusatzfelder,
                                            ASettings.mPreferenzen.getString(ISettings.KEY_EXP_M_NOTIZ, ""),
                                            storageHelper);
                                    mDateinamen.add(pdf_monat_kurz.getDateiName());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    mStatus = false;
                                }
                                break;
                            case IExport_Basis.LGAV:
                                Export_PDF_Zeitraum_LGAV pdf_monat_lgav;
                                try {
                                    pdf_monat_lgav = new Export_PDF_Zeitraum_LGAV(
                                            mContext,
                                            mMonat,
                                            bsSpalten,
                                            bsOptionen,
                                            bsZusatzfelder,
                                            ASettings.mPreferenzen.getString(ISettings.KEY_EXP_M_NOTIZ, ""),
                                            storageHelper);
                                    mDateinamen.add(pdf_monat_lgav.getDateiName());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    mStatus = false;
                                }
                                break;
                            default:
                                exportVariante = IExport_Basis.AUSFUERLICH;
                                Export_PDF_Zeitraum pdf_monat;
                                try {
                                    pdf_monat = new Export_PDF_Zeitraum(
                                            mContext,
                                            mMonat,
                                            bsSpalten,
                                            bsOptionen,
                                            bsZusatzfelder,
                                            ASettings.mPreferenzen.getString(ISettings.KEY_EXP_M_NOTIZ, ""),
                                            storageHelper);
                                    mDateinamen.add(pdf_monat.getDateiName());
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    mStatus = false;
                                }
                        }
                }
                berichtMonat.add(Calendar.MONTH, 1);
            }
            final boolean fStatus = mStatus;
            final ArrayList<String> fDateinamen = mDateinamen;
            mHandler.post(()->{
                // Fortschrittsdialog schliessen
                try {
                    if(mDialog.isShowing()) {
                        mDialog.dismiss();
                    }
                }catch (IllegalArgumentException e){
                    e.printStackTrace();
                }

                // Toast ausgeben
                Toast toast = Toast.makeText(
                        mContext,
                        fStatus ?
                                mContext.getString(R.string.export_erfolg) :
                                mContext.getString(R.string.export_miserfolg)
                        , Toast.LENGTH_LONG);
                toast.show();

                // Rückruf wenn speichern erfolgreich war
                if (fStatus) {
                    mCallback.onExportFinisch(
                            action,
                            exportDateityp,
                            IExport_Basis.PERIODE_MONAT,
                            fDateinamen,
                            kStarttag,
                            null);
                }
            });

        }).start();
    }

    private void updateAnzahlMonate(int anzahl){
        mAnzahlMonate = Math.min(anzahl, kStarttag.monateBis(ASettings.letzterAnzeigeTag) + 1);
        wAnzahlMonate.setText(String.valueOf(mAnzahlMonate));
        wNachwort.setText(getString(
                R.string.nachwort,
                mAnzahlMonate,
                mAnzahlMonate == 1 ? getString(R.string.monat):getString(R.string.monate),
                mAnzahlMonate == 1 ? getString(R.string.datei):getString(R.string.dateien)
        ));
    }
}
