/* 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.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Objects;

import askanimus.arbeitszeiterfassung2.Datum;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.StorageHelper;
import askanimus.arbeitszeiterfassung2.Zeitraum.Zeitraum_Woche;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitswoche.Arbeitswoche;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.betterpickers.calendardatepicker.CalendarDatePickerDialogFragment;
import askanimus.betterpickers.calendardatepicker.MonthAdapter;
import askanimus.betterpickers.numberpicker.NumberPickerBuilder;
import askanimus.betterpickers.numberpicker.NumberPickerDialogFragment;
import askanimus.betterpickers.weeknumberpicker.WeeknumberPickerBuilder;
import askanimus.betterpickers.weeknumberpicker.WeeknumberPickerDialogFragment;

/**
 * @author askanimus@gmail.com on 09.01.16.
 */
public class Export_Fragment_Woche
        extends
        Fragment
        implements
        IExport_Fragment,
        View.OnClickListener,
        CalendarDatePickerDialogFragment.OnDateSetListener,
        AppCompatCheckBox.OnCheckedChangeListener,
        RadioGroup.OnCheckedChangeListener,
        WeeknumberPickerDialogFragment.WeeknumberPickerDialogHandler,
        Fragment_Dialog_Spalten.EditSpaltenDialogListener,
        Fragment_Dialog_Zeilen.EditZeilenDialogListener,
        NumberPickerDialogFragment.NumberPickerDialogHandlerV2,
        AdapterView.OnItemSelectedListener {

    private final int TAG_WOCHE = 0;

    private BitSet bsSpalten;
    private BitSet bsSpaltenDeaktiv;
    private BitSet bsOptionen;
    private BitSet bsOptionenDeaktiv;
    private BitSet bsZusatzfelder;
    private String KEY_EXP_W_SPALTEN;
    private String KEY_EXP_W_ZEILEN ;
    private String KEY_EXP_W_ZUSATZ ;
    private int exportDateityp;

    private Datum kStarttag;
    private int mAnzahlWochen = 1;

    private static IExportFinishListener mCallback;

    private TextView wHintAuswahl;

    private RadioGroup rgGroesse;
    private RadioGroup rgLayout;

    private TextView wTrenner;
    private LinearLayout bTrenner;
    private TextView wWochennummer;
    private TextView wWochenbeginn;
    private TextView wAnzahlWochen;
    private TextView wNachwort;

    private TextView wNotiz;
    private LinearLayout bNotiz;

    private LinearLayout bOptionen;

    private AppCompatCheckBox cbEortSort;

    private Context mContext;

    /**
     * Gibt eine neue Instance des Fragments zurück
     */
   public static Export_Fragment_Woche newInstance(IExportFinishListener cb, long startdatun) {
        Export_Fragment_Woche fragment = new Export_Fragment_Woche();
        Bundle args = new Bundle();
        args.putLong(ISettings.ARG_DATUM, startdatun);
        fragment.setArguments(args);
        mCallback = cb;
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mContext = getContext();
        return inflater.inflate(R.layout.fragment_export_woche, 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());
        else
            kStarttag = new Datum(ASettings.aktDatum.getDate(), ASettings.aktJob.getWochenbeginn());

        kStarttag.setWocheBeginn(ASettings.aktJob.getWochenbeginn());

        if(kStarttag.liegtNach(ASettings.letzterAnzeigeTag)){
            kStarttag.set(ASettings.letzterAnzeigeTag.getCalendar());
            kStarttag.setDatumAufWochenbeginn();
        }

        // den Datumsbereich der Woche ermitteln
        Datum kEndtag = new Datum(kStarttag);
        kEndtag.add(Calendar.DAY_OF_MONTH, 6);
        if(kEndtag.liegtNach(ASettings.letzterAnzeigeTag)){
           kEndtag.set(ASettings.letzterAnzeigeTag.getCalendar());
        }

        // die Oberfläche anpassen
        View rootView = getView();
        if (rootView != null) {
            // die einzelnen Bedienelemente finden
            wTrenner = rootView.findViewById(R.id.EW_wert_trenner);
            bTrenner = rootView.findViewById(R.id.EW_box_trenner);
            rgGroesse = rootView.findViewById(R.id.EW_gruppe_groesse);
            rgLayout = rootView.findViewById(R.id.EW_gruppe_layout);
            wWochenbeginn = rootView.findViewById(R.id.EW_wert_wochebereich);
            wWochennummer = rootView.findViewById(R.id.EW_wert_wochennummer);
            wAnzahlWochen = rootView.findViewById(R.id.EW_wert_anzahl);
            wNachwort = rootView.findViewById(R.id.EW_nachwort);
            wNotiz = rootView.findViewById(R.id.EW_wert_notiz);
            bNotiz = rootView.findViewById(R.id.EW_box_notiz);
            bOptionen = rootView.findViewById(R.id.EW_pdfOptionen);
            cbEortSort = rootView.findViewById(R.id.EW_button_sort_eort);
            RadioGroup rgDateityp = rootView.findViewById(R.id.EW_gruppe_typ);
            wHintAuswahl = rootView.findViewById(R.id.EW_hint_dateityp);
            AppCompatCheckBox cbZusammenfassung = rootView.findViewById(R.id.EW_button_zus);
            ImageButton ibEditSpalten = rootView.findViewById(R.id.EW_button_edit_spalten);
            ImageButton ibEditZeilen = rootView.findViewById(R.id.EW_button_edit_zeilen);
            AppCompatSpinner spinnerFontSize = rootView.findViewById(R.id.EW_spinner_fontgroesse);

            // den Datumsbereich der Woche eintragen
            wWochenbeginn.setText(
                    kStarttag.getString_Datum_Bereich(
                            mContext,
                            0,
                            kStarttag.tageBis(kEndtag),
                            Calendar.DAY_OF_MONTH
                    )
            );
            // die Wochennummer
            wWochennummer.setText(getString(R.string.export_woche_nummer, kStarttag.get(Calendar.WEEK_OF_YEAR), kStarttag.get(Calendar.YEAR)));
            updateAnzahlWochen(mAnzahlWochen);

            // bis zur Version 10291 war für alle Exporte nur ein gemeinsamer Dateityp gespeichert
            exportDateityp = ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_TYP_WOCHE, ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_TYP, IExport_Basis.TYP_PDF));

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

            long i = ASettings.aktJob.getId();
            KEY_EXP_W_SPALTEN = ISettings.KEY_EXP_W_SPALTEN + i;
            KEY_EXP_W_ZEILEN =  ISettings.KEY_EXP_W_ZEILEN + i;
            KEY_EXP_W_ZUSATZ =  ISettings.KEY_EXP_W_ZUSATZ + i;
            initSpaltenZeilen();

            // Handler registrieren
            wTrenner.setOnClickListener(this);
            rgGroesse.setOnCheckedChangeListener(this);
            rgLayout.setOnCheckedChangeListener(this);
            wWochenbeginn.setOnClickListener(this);
            wWochennummer.setOnClickListener(this);
            wAnzahlWochen.setOnClickListener(this);
            wNotiz.setOnClickListener(this);
            cbEortSort.setOnCheckedChangeListener(this);
            ibEditSpalten.setOnClickListener(this);
            ibEditZeilen.setOnClickListener(this);
            rgDateityp.setOnCheckedChangeListener(this);
            cbZusammenfassung.setOnCheckedChangeListener(this);
            spinnerFontSize.setOnItemSelectedListener(this);

            // die Knopffarben
            // Radiobuttons Dateitypen
            for (View v : rgDateityp.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            // Radiobuttons Seitengröße
            for (View v : rgGroesse.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }
            // Radiobuttons Seitenformat
            for (View v : rgLayout.getTouchables()) {
                CompoundButtonCompat.setButtonTintList(
                        ((AppCompatRadioButton) v),
                        ASettings.aktJob.getFarbe_Radio());
            }

            // Checkboxen
            CompoundButtonCompat.setButtonTintList(
                    cbEortSort,
                    ASettings.aktJob.getFarbe_Radio()
            );
            CompoundButtonCompat.setButtonTintList(
                    cbZusammenfassung,
                    ASettings.aktJob.getFarbe_Radio()
            );
            // Spalte- und Zeilenknöpfe
            ViewCompat.setBackgroundTintList(ibEditSpalten, ASettings.aktJob.getFarbe_Button());
            ViewCompat.setBackgroundTintList(ibEditZeilen, ASettings.aktJob.getFarbe_Button());

            // Werte an Hand der letzten Auswahl vorbelegen
            // Die Dateitypauswahl
            int d = exportDateityp;
            rgDateityp.clearCheck();
            switch (d) {
                case IExport_Basis.TYP_CSV:
                    rgDateityp.check(R.id.EW_button_csv);
                    bTrenner.setVisibility(View.VISIBLE);
                /*bUnterschriften.setVisibility(View.GONE);
                cbUnterschrift.setVisibility(View.GONE);*/
                    wHintAuswahl.setText(R.string.export_hint_csv);
                    break;
                case IExport_Basis.TYP_CAL_ICS:
                    rgDateityp.check(R.id.EW_button_ics);
                    wHintAuswahl.setText(R.string.export_hint_ics_cal);
                    break;
                case IExport_Basis.TYP_CAL_CSV:
                    rgDateityp.check(R.id.EW_button_cal);
                    wHintAuswahl.setText(R.string.export_hint_csv_cal);
                    break;
                default:
                    rgDateityp.check(R.id.EW_button_pdf);
                    bTrenner.setVisibility(View.GONE);
                    wHintAuswahl.setText(R.string.export_hint_pdf);
                    break;
            }

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

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

            // das Trennzeichen für den CSV export
            wTrenner.setText(ASettings.mPreferenzen.getString(ISettings.KEY_EXPORT_CSV_TRENNER, ";"));

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

            // die Formatauswahl
            b = bsOptionen.get(IExport_Basis.OPTION_LAYOUT_QUEER);
            rgLayout.clearCheck();
            rgLayout.check(b ? R.id.EW_button_quer : R.id.EW_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_W_NOTIZ, ""));

            // die Vorauswahl der Schriftgrösse
            spinnerFontSize.setSelection(ASettings.mPreferenzen.getInt(ISettings.KEY_EXP_W_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());
    }

    /*
     * Handlerfunktionen
     */

    @Override
    public void onClick(View v) {
        FragmentManager fManager;
        try {
            fManager = getParentFragmentManager();
            int id = v.getId();
            if (id == R.id.EW_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_W_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.EW_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.EW_wert_wochennummer) {
                WeeknumberPickerBuilder wnp = new WeeknumberPickerBuilder()
                        .setFragmentManager(fManager)
                        .setStyleResId(ASettings.themePicker)
                        .setMinDate(ASettings.aktJob.getStartDatum().get(Calendar.YEAR), ASettings.aktJob.getStartDatum().get(Calendar.WEEK_OF_YEAR))
                        .setMaxDate(ASettings.letzterAnzeigeTag.get(Calendar.YEAR), ASettings.letzterAnzeigeTag.get(Calendar.WEEK_OF_YEAR))
                        .setReference(TAG_WOCHE)
                        .setTargetFragment(this);
                wnp.show();
            } else if (id == R.id.EW_wert_wochebereich) {
                CalendarDatePickerDialogFragment vonKalenderPicker =
                        new CalendarDatePickerDialogFragment()
                                .setOnDateSetListener(this)
                                .setFirstDayOfWeek(ASettings.aktJob.getWochenbeginn())
                                .setPreselectedDate(kStarttag.get(Calendar.YEAR),
                                        kStarttag.get(Calendar.MONTH) - 1,
                                        kStarttag.get(Calendar.DAY_OF_MONTH));
                if (ASettings.aktJob.getStartDatum().liegtNach(ASettings.aktDatum)) {
                    vonKalenderPicker.setDateRange(
                            new MonthAdapter.CalendarDay(
                                    ASettings.aktJob.getStartDatum().get(Calendar.YEAR),
                                    ASettings.aktJob.getStartDatum().get(Calendar.MONTH) - 1,
                                    ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_MONTH)),
                            new MonthAdapter.CalendarDay(
                                    ASettings.aktJob.getStartDatum().get(Calendar.YEAR),
                                    ASettings.aktJob.getStartDatum().get(Calendar.MONTH) - 1,
                                    ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_MONTH)));
                    vonKalenderPicker.setPreselectedDate(
                            ASettings.aktJob.getStartDatum().get(Calendar.YEAR),
                            ASettings.aktJob.getStartDatum().get(Calendar.MONTH) - 1,
                            ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_MONTH));

                } else {
                    vonKalenderPicker.setDateRange(
                            new MonthAdapter.CalendarDay(
                                    ASettings.aktJob.getStartDatum().get(Calendar.YEAR),
                                    ASettings.aktJob.getStartDatum().get(Calendar.MONTH) - 1,
                                    ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_MONTH)),
                            new MonthAdapter.CalendarDay(
                                    ASettings.letzterAnzeigeTag.get(Calendar.YEAR),
                                    ASettings.letzterAnzeigeTag.get(Calendar.MONTH) - 1,
                                    ASettings.letzterAnzeigeTag.get(Calendar.DAY_OF_MONTH)));
                    vonKalenderPicker.setPreselectedDate(
                            kStarttag.get(Calendar.YEAR),
                            kStarttag.get(Calendar.MONTH) - 1,
                            kStarttag.get(Calendar.DAY_OF_MONTH));
                }

               if (ASettings.isThemaDunkel) {
                    vonKalenderPicker.setThemeDark();
                } else {
                    vonKalenderPicker.setThemeLight();
                }
                vonKalenderPicker.show(fManager, getString(R.string.woche));
            } else if (id == R.id.EW_wert_anzahl) {
                int mMaxAnzahl;
                try {
                    fManager = getParentFragmentManager();
                    mMaxAnzahl = kStarttag.wochenBis(ASettings.letzterAnzeigeTag) + 1;
                    NumberPickerBuilder prozentPicker = new NumberPickerBuilder()
                            .setFragmentManager(fManager)
                            .setStyleResId(ASettings.themePicker)
                            .setMinNumber(BigDecimal.valueOf(1))
                            .setMaxNumber(BigDecimal.valueOf(mMaxAnzahl))
                            .setLabelText(getString(R.string.wochen))
                            //.setCurrentNumber(anzahlJahre)
                            .setPlusMinusVisibility(View.INVISIBLE)
                            .setDecimalVisibility(View.INVISIBLE)
                            .setReference(R.id.EW_wert_anzahl)
                            .setTargetFragment(this);
                    prozentPicker.show();
                } catch (IllegalStateException ise) {
                    ise.printStackTrace();
                }
            } else if (id == R.id.EW_button_edit_spalten) {// Spaltenauswahldialog
                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.EW_button_edit_zeilen) {// Zeilenauswahldialog
                Fragment_Dialog_Zeilen mDialogZeilen = new Fragment_Dialog_Zeilen(
                        ASettings.aktJob,
                        bsOptionen,
                        bsOptionenDeaktiv,
                        this,
                        IExport_Basis.PERIODE_WOCHE);
                /*mDialogZeilen.setup(
                        ASettings.aktJob,
                        bsOptionen,
                        bsOptionenDeaktiv,
                        this,
                        IExport_Basis.PERIODE_WOCHE);*/
                mDialogZeilen.show(fManager, "EditZeilenDialog");
            }
        } catch (IllegalStateException ignore){
        }
    }

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

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
        int id = group.getId();
        if (id == R.id.EW_gruppe_groesse){
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_A3, (checkedId == R.id.EW_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_EXP_W_ZEILEN, value);
        } else if (id == R.id.EW_gruppe_layout) {
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_QUEER, checkedId == R.id.EW_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_EXP_W_ZEILEN, value);
        } else if (id == R.id.EW_gruppe_typ) {
            if (checkedId == R.id.EW_button_ics) {
                exportDateityp = IExport_Basis.TYP_CAL_ICS;
                bOptionen.setVisibility(View.GONE);
                wHintAuswahl.setText(R.string.export_hint_ics_cal);
            } else if (checkedId == R.id.EW_button_csv) {
                exportDateityp = IExport_Basis.TYP_CSV;
                bTrenner.setVisibility(View.VISIBLE);
                rgGroesse.setVisibility(View.GONE);
                rgLayout.setVisibility(View.GONE);
                bOptionen.setVisibility(View.VISIBLE);
                bNotiz.setVisibility(View.GONE);
                wHintAuswahl.setText(R.string.export_hint_csv);
                if (bsOptionenDeaktiv != null) {
                    bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, true);
                }
            } else if (checkedId == R.id.EW_button_cal) {
                exportDateityp = IExport_Basis.TYP_CAL_CSV;
                bOptionen.setVisibility(View.GONE);
                wHintAuswahl.setText(R.string.export_hint_csv_cal);
            } else {
                exportDateityp = IExport_Basis.TYP_PDF;
                bTrenner.setVisibility(View.GONE);
                rgGroesse.setVisibility(View.VISIBLE);
                rgLayout.setVisibility(View.VISIBLE);
                bOptionen.setVisibility(View.VISIBLE);
                bNotiz.setVisibility(View.VISIBLE);
                wHintAuswahl.setText(R.string.export_hint_pdf);
                if (bsOptionenDeaktiv != null) {
                    bsOptionenDeaktiv.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, false);
                }
            }
            mEdit.putInt(ISettings.KEY_EXP_TYP_WOCHE, exportDateityp);
        }

        mEdit.apply();
    }

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

        mEdit.apply();
    }
    /*
     * Dialogrückgaben
     */
    @Override
    public void onDateSet(CalendarDatePickerDialogFragment dialog, int year, int monthOfYear, int dayOfMonth) {
        if (Objects.equals(dialog.getTag(), getString(R.string.woche))) {
            kStarttag.set(year, monthOfYear + 1, dayOfMonth);
            kStarttag.setWocheBeginn(ASettings.aktJob.getWochenbeginn());
            Datum kEndtag = new Datum(kStarttag.getTimeInMillis(), ASettings.aktJob.getWochenbeginn());
            kEndtag.add(Calendar.DAY_OF_MONTH, 6);
            wWochennummer.setText(getString(R.string.export_woche_nummer, kStarttag.get(Calendar.WEEK_OF_YEAR), kStarttag.get(Calendar.YEAR)));
            wWochenbeginn.setText(
                    kStarttag.getString_Datum_Bereich(
                            mContext,
                            0,
                            kStarttag.tageBis(kEndtag),
                            Calendar.DAY_OF_MONTH
                    )
            );
            updateAnzahlWochen(mAnzahlWochen);
        }
    }



    @Override
    public void onDialogWeeknumberSet(int reference, int year, int week) {
        if (reference == TAG_WOCHE) {
            int wMin = ASettings.aktJob.getStartDatum().get(Calendar.YEAR) * 52 + ((ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_YEAR + 7) / 7));
            int wMax = ASettings.letzterAnzeigeTag.get(Calendar.YEAR) * 52 + ((ASettings.letzterAnzeigeTag.get(Calendar.DAY_OF_YEAR) + 7) / 7);
            int wWahl = year * 52 + week;
            if (wWahl < wMin) {
                Toast.makeText(mContext, R.string.datum_vor_beginn, Toast.LENGTH_LONG).show();
                year = ASettings.aktJob.getStartDatum().get(Calendar.YEAR);
                week = ASettings.aktJob.getStartDatum().get(Calendar.WEEK_OF_YEAR);
            } else if (ASettings.aktJob.isSetEnde() && (wMax < wWahl)) {
                Toast.makeText(mContext, R.string.datum_nach_ende, Toast.LENGTH_LONG).show();
                year = ASettings.letzterAnzeigeTag.get(Calendar.YEAR);
                week = ASettings.letzterAnzeigeTag.get(Calendar.WEEK_OF_YEAR);
            }
            kStarttag.setJahr(year);
            kStarttag.setWoche(week);
            kStarttag.setWocheBeginn(ASettings.aktJob.getWochenbeginn());
            Datum kEndtag = new Datum(kStarttag.getTimeInMillis(), ASettings.aktJob.getWochenbeginn());
            kEndtag.add(Calendar.DAY_OF_MONTH, 6);
            wWochennummer.setText(
                    getString(
                            R.string.export_woche_nummer,
                            kStarttag.get(Calendar.WEEK_OF_YEAR),
                            kStarttag.get(Calendar.YEAR)
                    )
            );
            wWochenbeginn.setText(
                    kStarttag.getString_Datum_Bereich(
                            mContext,
                            0,
                            kStarttag.tageBis(kEndtag),
                            Calendar.DAY_OF_MONTH
                    )
            );
            updateAnzahlWochen(mAnzahlWochen);
        }
    }

    // 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_W_FONTSIZE, position).apply();
    }

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

    //
    // die Bitsets für Spalten und Zeilen initialisieren
    //
    private void initSpaltenZeilen() {
        int mWert;

        // auszugebende Spalten
        mWert = ASettings.mPreferenzen.getInt(KEY_EXP_W_SPALTEN, IExport_Basis.DEF_SPALTEN);
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_SPALTE; i++) {
            bsSpalten.set(i, (mWert & (1 << i)) != 0);
        }

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

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

        // im Wochenbericht brauchen keine Wochennummer in der Tabelle angezeigt werden
        bsOptionenDeaktiv.set(IExport_Basis.OPTION_WOCHENNUMMER, true);
        bsOptionen.set(IExport_Basis.OPTION_WOCHENNUMMER, 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);
        }
        // auszugebende Zeilen und optionale Tabellen, Zusätze
        mWert = ASettings.mPreferenzen.getInt(KEY_EXP_W_ZEILEN, 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);
        }

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

    @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_EXP_W_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_EXP_W_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_EXP_W_ZEILEN, value).apply();
        }
        ASettings.aktJob.setUnterschrift_AG(unetrschriftAG);
        ASettings.aktJob.setUnterschrift_AN(unterschriftAN);
        ASettings.aktJob.schreibeJob();
    }

    /*
     * Ausführen der gewünschten Aktion
     */
    @Override
    public void action(int action, Arbeitsplatz job, StorageHelper storageHelper/*final String pfad*/){
        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/*final String pfad*/) {
        final 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 berichtWoche = new Datum(kStarttag);
            boolean mStatus = true;
            ArrayList<String> mDateinamen = new ArrayList<>();
            Zeitraum_Woche mWoche;

            for (int i = 0; i < mAnzahlWochen; i++) {
                mWoche = new Zeitraum_Woche(
                        new Arbeitswoche(
                                berichtWoche.getTimeInMillis(),
                                job));
                switch (exportDateityp) {
                    case IExport_Basis.TYP_CAL_ICS:
                        Export_ICS mICSWoche;
                        try {
                            mICSWoche = new Export_ICS(
                                    mContext,
                                    mWoche,
                                    bsOptionen,
                                    storageHelper
                            );
                            mDateinamen.add(mICSWoche.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    case IExport_Basis.TYP_CSV:
                        Export_CSV_Zeitraum mCSVWoche;
                        try {
                            mCSVWoche = new Export_CSV_Zeitraum(
                                    mContext,
                                    mWoche,
                                    bsSpalten,
                                    bsOptionen,
                                    bsZusatzfelder,
                                    storageHelper
                            );
                            mDateinamen.add(mCSVWoche.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    case IExport_Basis.TYP_CAL_CSV:
                        Export_CAL mCALWoche;
                        try {
                            mCALWoche = new Export_CAL(
                                    mContext,
                                    mWoche,
                                    bsOptionen,
                                    storageHelper
                            );
                            mDateinamen.add(mCALWoche.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                        break;
                    default:
                        exportDateityp = IExport_Basis.TYP_PDF;
                        Export_PDF_Zeitraum mPDFWoche;
                        try {
                            mPDFWoche = new Export_PDF_Zeitraum(
                                    mContext,
                                    mWoche,
                                    bsSpalten,
                                    bsOptionen,
                                    bsZusatzfelder,
                                    ASettings.mPreferenzen.getString(ISettings.KEY_EXP_W_NOTIZ, ""),
                                    storageHelper);
                            mDateinamen.add(mPDFWoche.getDateiName());
                        } catch (Exception e) {
                            e.printStackTrace();
                            mStatus = false;
                        }
                }
                berichtWoche.add(Calendar.WEEK_OF_YEAR, 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_WOCHE,
                            fDateinamen,
                            kStarttag,
                            null);
                }
            });

        }).start();
    }

    private void updateAnzahlWochen(int anzahl){
        mAnzahlWochen = Math.min(anzahl, kStarttag.wochenBis(ASettings.letzterAnzeigeTag) + 1);
        wAnzahlWochen.setText(String.valueOf(mAnzahlWochen));
        wNachwort.setText(getString(
                R.string.nachwort,
                mAnzahlWochen,
                mAnzahlWochen == 1 ? getString(R.string.woche):getString(R.string.wochen),
                mAnzahlWochen == 1 ? getString(R.string.datei):getString(R.string.dateien)
        ));
    }
}

