/* 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.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.AppCompatRadioButton;
import androidx.appcompat.widget.AppCompatSpinner;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
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_Jahr;
import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.arbeitsjahr.Arbeitsjahr_summe;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.ZusatzWertListe;
import askanimus.betterpickers.numberpicker.NumberPickerBuilder;
import askanimus.betterpickers.numberpicker.NumberPickerDialogFragment;

/**
 * @author askanimus@gmail.com on 09.01.16.
 */
public class Export_Fragment_Jahr
        extends Fragment
        implements
        IExport_Fragment,
        View.OnClickListener,
        RadioGroup.OnCheckedChangeListener,
        NumberPickerDialogFragment.NumberPickerDialogHandlerV2,
        TabellenExportViewAdapter.ButtonClickListener ,
        AdapterView.OnItemSelectedListener,
        CompoundButton.OnCheckedChangeListener {

    private BitSet bsTabellen;
    private BitSet bsTabellenDeaktiviert;
    private BitSet bsOptionen;
    private BitSet bsZusatzfelder;

    private String KEY_EXP_J_TABELLEN;
    private String KEY_EXP_J_OPTIONEN;
    private String KEY_EXP_J_ZUSATZ;
    private int exportDateityp;

    private Datum kStarttag;

    private int anzahlJahre = 1;

    private static IExportFinishListener mCallback;

    private final DateFormat fBereich = DateFormat.getDateInstance(DateFormat.MEDIUM);

    private RadioGroup rgGroesse;
    private RadioGroup rgLayout;

    private TextView wTrenner;
    private LinearLayout bTrenner;
    private TextView wJahr;
    private TextView wJahrAnzahl;
    private TextView wJahrNachwort;
    private SwitchCompat swUnterschriften;
    TextView wArbeitgeber;
    TextView wArbeitnehmer;
    private LinearLayout bUnterschriften;

     private ZusatzWertListe zusatzwerteDummy;

    private Context mContext;

    //
    // die Bitsets für Tabellen initialisieren
    //

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
   public static Export_Fragment_Jahr newInstance(IExportFinishListener cb, int jahr) {
       mCallback = cb;
        Export_Fragment_Jahr fragment = new Export_Fragment_Jahr();
        Bundle args = new Bundle();
        args.putInt(ISettings.ARG_JAHR, jahr);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       mContext = getContext();
        return Objects.requireNonNull(inflater).inflate(R.layout.fragment_export_jahr, container, false);
    }



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

    private void resume() {
        // zu schreibenden Monat ermitteln
        Bundle mArgs = getArguments();
        if (mArgs != null)
            kStarttag = new Datum(mArgs.getInt(ISettings.ARG_JAHR), 1,
                    ASettings.aktJob.getMonatsbeginn(), ASettings.aktJob.getWochenbeginn());
        else
            kStarttag = new Datum(ASettings.aktDatum.get(Calendar.YEAR), 1,
                    ASettings.aktJob.getMonatsbeginn(), ASettings.aktJob.getWochenbeginn());

        // der Datumsbereich
        if(kStarttag.liegtVor(ASettings.aktJob.getStartDatum())){
            kStarttag.set(ASettings.aktJob.getStartDatum().getCalendar());
        }

        Datum kEndtag = new Datum(kStarttag);
        kEndtag.add(Calendar.DAY_OF_YEAR, kStarttag.getAktuellMaximum(Calendar.DAY_OF_YEAR) - 1);
        if (kEndtag.liegtNach(ASettings.letzterAnzeigeTag))
            kEndtag.set(ASettings.letzterAnzeigeTag.getCalendar());

        if(kStarttag.liegtNach(kEndtag)){
            kStarttag.set(kEndtag.getCalendar());
            kStarttag.setTag(ASettings.aktJob.getMonatsbeginn());
            kStarttag.set(kEndtag.get(Calendar.YEAR), 1,  ASettings.aktJob.getMonatsbeginn());
            if(kStarttag.liegtVor(ASettings.aktJob.getStartDatum())){
                kStarttag.set(ASettings.aktJob.getStartDatum().getCalendar());
            }
        }

        // die Oberfläche anpassen
        View rootView = getView();
        if (rootView != null) {
            // Anzeigeelemente finden
            rgGroesse = rootView.findViewById(R.id.EJ_gruppe_groesse);
            rgLayout = rootView.findViewById(R.id.EJ_gruppe_layout);
            wTrenner = rootView.findViewById(R.id.EJ_wert_trenner);
            bTrenner =  rootView.findViewById(R.id.EJ_box_trenner);
            wJahr = rootView.findViewById(R.id.EJ_wert_jahr);
            wJahrAnzahl = rootView.findViewById(R.id.EJ_wert_anzahl);
            wJahrNachwort = rootView.findViewById(R.id.EJ_nachwort);
            RadioGroup rgDateityp = rootView.findViewById(R.id.EJ_gruppe_typ);
            AppCompatSpinner spinnerFontSize = rootView.findViewById(R.id.EJ_spinner_fontgroesse);
            swUnterschriften = rootView.findViewById(R.id.EJ_switch_unterschrift);
            wArbeitgeber =  rootView.findViewById(R.id.EJ_text_arbeitgeber);
            wArbeitnehmer =  rootView.findViewById(R.id.EJ_text_arbeitneher);
            bUnterschriften = rootView.findViewById(R.id.EJ_box_unterschrift);

            // Farbgebung der Knöpfe anpassen
            // 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());
            }
            // Switch Unterschriften
            swUnterschriften.setThumbTintList(ASettings.aktJob.getFarbe_Thumb());
            swUnterschriften.setTrackTintList(ASettings.aktJob.getFarbe_Trak());

            // Datumsauswahl vorbelegen
            wJahr.setText(String.valueOf(kStarttag.get(Calendar.YEAR))); // der Datumsbereich
            /*String sbereich = "( " + fBereich.format(kStarttag.getTime()) + " - ";
            sbereich += fBereich.format(kEndtag.getTime()) + " )";*/
            wJahrAnzahl.setText(String.valueOf(anzahlJahre));
            wJahrNachwort.setText(getString(
                    R.string.nachwort,
                    anzahlJahre,
                    anzahlJahre == 1 ? getString(R.string.jahr):getString(R.string.jahre),
                    anzahlJahre == 1 ? getString(R.string.datei):getString(R.string.dateien)
                    ));

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

            // die Bitsets für Spalten, Zeilen/Optionen und Zusatzwerte initialisieren
            bsTabellen = new BitSet(IExport_Basis.DEF_MAXBIT_TABELLEN);
            bsTabellenDeaktiviert = new BitSet(IExport_Basis.DEF_MAXBIT_TABELLEN);
            bsOptionen = new BitSet(IExport_Basis.DEF_MAXBIT_OPTION);
            bsZusatzfelder = new BitSet();

            long i = ASettings.aktJob.getId();
            KEY_EXP_J_TABELLEN = ISettings.KEY_EXP_J_TABELLEN + i;
            KEY_EXP_J_OPTIONEN = ISettings.KEY_EXP_J_OPTIONEN + i;
            KEY_EXP_J_ZUSATZ =   ISettings.KEY_EXP_J_ZUSATZ + i;

            // Dummyliste der Zusatzwerte ohne Textfelder erstellen
            // wird zum darstellen Tabellenoptionen benötigt
            zusatzwerteDummy = new ZusatzWertListe(ASettings.aktJob.getZusatzfeldListe(), false);
            initSpaltenZeilen();

            // Handler definieren
            rgGroesse.setOnCheckedChangeListener(this);
            rgLayout.setOnCheckedChangeListener(this);
            wTrenner.setOnClickListener(this);
            wJahr.setOnClickListener(this);
            wJahrAnzahl.setOnClickListener(this);
            rgDateityp.setOnCheckedChangeListener(this);
            spinnerFontSize.setOnItemSelectedListener(this);
            swUnterschriften.setOnCheckedChangeListener(this);
            wArbeitgeber.setOnClickListener(this);
            wArbeitnehmer.setOnClickListener(this);

            // Werte vorbelegen
            // die Auswahl des Dateityps
            int d = exportDateityp;
            rgDateityp.clearCheck();
            rgDateityp.check((d == IExport_Basis.TYP_CSV) ? R.id.EJ_button_csv : R.id.EJ_button_pdf);

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

            //die Auswahl des SeitenLayouts
            b = bsOptionen.get(IExport_Basis.OPTION_LAYOUT_QUEER);
            rgLayout.clearCheck();
            rgLayout.check(b ? R.id.EJ_button_quer : R.id.EJ_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, ";"));

            // die Liste der Tabellen anzeigen
            RecyclerView gZusatzwerte = rootView.findViewById(R.id.EJ_liste_zusatzwerte);
            TabellenExportViewAdapter viewAdapter =
                    new TabellenExportViewAdapter(
                            mContext,
                            zusatzwerteDummy,
                            bsTabellen,
                            bsTabellenDeaktiviert,
                            bsZusatzfelder,
                            this);
            GridLayoutManager layoutManger = new GridLayoutManager(mContext, 2);
            gZusatzwerte.setAdapter(viewAdapter);
            gZusatzwerte.setLayoutManager(layoutManger);

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

            // die Unterschriften
            swUnterschriften.setChecked(bsOptionen.get(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT));
            wArbeitgeber.setText(ASettings.aktJob.getUnterschrift_AG());
            wArbeitnehmer.setText(ASettings.aktJob.getUnterschrift_AN());
            bUnterschriften.setVisibility(swUnterschriften.isChecked() ? View.VISIBLE : View.GONE);
        }
    }

    /*
     * Handlerfunktionen
     */

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.EJ_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.setMaxLines(8);
            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.EJ_wert_jahr) {
            int mMinJahr;
            FragmentManager fManager;
            try {
                fManager = getParentFragmentManager();
                if (ASettings.aktJob.getStartDatum().get(Calendar.DAY_OF_MONTH) < ASettings.aktJob.getMonatsbeginn())
                    mMinJahr = ASettings.aktJob.getStartDatum().get(Calendar.YEAR) - 1;
                else
                    mMinJahr = ASettings.aktJob.getStartDatum().get(Calendar.YEAR);
                NumberPickerBuilder prozentPicker = new NumberPickerBuilder()
                        .setFragmentManager(fManager)
                        .setStyleResId(ASettings.themePicker)
                        .setMinNumber(BigDecimal.valueOf(mMinJahr))
                        .setMaxNumber(BigDecimal.valueOf(ASettings.letzterAnzeigeTag.get(Calendar.YEAR)))
                        .setLabelText(getString(R.string.jahr))
                        .setCurrentNumber(20)
                        .setPlusMinusVisibility(View.INVISIBLE)
                        .setDecimalVisibility(View.INVISIBLE)
                        .setReference(R.id.EJ_wert_jahr)
                        .setTargetFragment(this);
                prozentPicker.show();
            } catch (IllegalStateException ise){
                ise.printStackTrace();
            }
        }  else if (id == R.id.EJ_wert_anzahl) {
            int mMaxAnzahl;
            FragmentManager fManager;
            try {
                fManager = getParentFragmentManager();
                mMaxAnzahl = 1 + ASettings.getLetzterAnzeigeTag(ASettings.aktJob).getJahr() - kStarttag.getJahr();
                NumberPickerBuilder prozentPicker = new NumberPickerBuilder()
                        .setFragmentManager(fManager)
                        .setStyleResId(ASettings.themePicker)
                        .setMinNumber(BigDecimal.valueOf(1))
                        .setMaxNumber(BigDecimal.valueOf(mMaxAnzahl))
                        .setLabelText(getString(R.string.jahre))
                        //.setCurrentNumber(anzahlJahre)
                        .setPlusMinusVisibility(View.INVISIBLE)
                        .setDecimalVisibility(View.INVISIBLE)
                        .setReference(R.id.EJ_wert_anzahl)
                        .setTargetFragment(this);
                prozentPicker.show();
            } catch (IllegalStateException ise){
                ise.printStackTrace();
            }
        }else if (id == R.id.EJ_text_arbeitgeber){
                final InputMethodManager immNotiz =
                        (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final AlertDialog.Builder mDialogNotiz = new AlertDialog.Builder(mContext);
                final EditText mInputArbeitgeber = new EditText(getActivity());
                mInputArbeitgeber.setText(wArbeitgeber.getText());
                mInputArbeitgeber.setSelection(wArbeitgeber.getText().length());
                mInputArbeitgeber.setFocusableInTouchMode(true);
                mInputArbeitgeber.requestFocus();
                mInputArbeitgeber.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
                mDialogNotiz.setTitle(R.string.visum_titel);
                mDialogNotiz.setView(mInputArbeitgeber);
                mDialogNotiz.setPositiveButton(getString(android.R.string.ok), (dialog, whichButton) -> {
                    wArbeitgeber.setText(mInputArbeitgeber.getText());
                    ASettings.aktJob.setUnterschrift_AG(mInputArbeitgeber.getText().toString());
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputArbeitgeber.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.setNegativeButton(getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputArbeitgeber.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.show();
                if (immNotiz != null) {
                    immNotiz.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
        } else if (id == R.id.EJ_text_arbeitneher){
                final InputMethodManager immNotiz =
                        (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
                final AlertDialog.Builder mDialogNotiz = new AlertDialog.Builder(mContext);
                final EditText mInputArbeitnehmer = new EditText(getActivity());
                mInputArbeitnehmer.setText(wArbeitgeber.getText());
                mInputArbeitnehmer.setSelection(wArbeitgeber.getText().length());
                mInputArbeitnehmer.setFocusableInTouchMode(true);
                mInputArbeitnehmer.requestFocus();
                mInputArbeitnehmer.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
                mDialogNotiz.setTitle(R.string.visum_titel);
                mDialogNotiz.setView(mInputArbeitnehmer);
                mDialogNotiz.setPositiveButton(getString(android.R.string.ok), (dialog, whichButton) -> {
                    wArbeitnehmer.setText(mInputArbeitnehmer.getText());
                    ASettings.aktJob.setUnterschrift_AN(mInputArbeitnehmer.getText().toString());
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputArbeitnehmer.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.setNegativeButton(getString(android.R.string.cancel), (dialog, whichButton) -> {
                    // Abbruchknopf gedrückt
                    if (immNotiz != null) {
                        immNotiz.hideSoftInputFromWindow(mInputArbeitnehmer.getWindowToken(), 0);
                    }
                });
                mDialogNotiz.show();
                if (immNotiz != null) {
                    immNotiz.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
        }
    }


    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
        int id = group.getId();
        if (id == R.id.EJ_gruppe_groesse){
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_A3, (checkedId == R.id.EJ_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_J_OPTIONEN, value).apply();
        } else if (id == R.id.EJ_gruppe_layout) {
            bsOptionen.set(IExport_Basis.OPTION_LAYOUT_QUEER, (checkedId == R.id.EJ_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_J_OPTIONEN, value).apply();
        } else if (id == R.id.EJ_gruppe_typ) {
            if (checkedId == R.id.EJ_button_csv) {
                exportDateityp = IExport_Basis.TYP_CSV;
                bTrenner.setVisibility(View.VISIBLE);
                rgGroesse.setVisibility(View.GONE);
                rgLayout.setVisibility(View.GONE);
            } else {
                exportDateityp = IExport_Basis.TYP_PDF;
                bTrenner.setVisibility(View.GONE);
                rgGroesse.setVisibility(View.VISIBLE);
                rgLayout.setVisibility(View.VISIBLE);
            }
            mEdit.putInt(ISettings.KEY_EXP_TYP_JAHR, exportDateityp).apply();
        }
        //mEdit.apply();
    }


    @Override
    public void onDialogNumberSet(int reference, BigInteger number, double decimal, boolean isNegative, BigDecimal fullNumber) {
        if(reference == R.id.EJ_wert_jahr) {
            kStarttag.set(number.intValue(), 1, ASettings.aktJob.getMonatsbeginn());

            Datum kEndTag = new Datum(kStarttag.getTimeInMillis(), ASettings.aktJob.getWochenbeginn());
            kEndTag.add(Calendar.DAY_OF_YEAR, kStarttag.getAktuellMaximum(Calendar.DAY_OF_YEAR) - 1);

            if (ASettings.aktJob.isSetEnde() && kEndTag.liegtNach(ASettings.aktJob.getEndDatum()))
                kEndTag.set(ASettings.aktJob.getEndDatum().getDate());

            /*String sbereich = "( " + fBereich.format(kStarttag.getTime()) + " - ";
            sbereich += fBereich.format(kEndTag.getTime()) + " )";
            wJahrBereich.setText(sbereich);*/
            wJahr.setText(String.valueOf(kStarttag.get(Calendar.YEAR)));
        } else {
            anzahlJahre = number.intValue();
        }

        anzahlJahre = Math.min(anzahlJahre, 1 + ASettings.getLetzterAnzeigeTag(ASettings.aktJob).getJahr() - kStarttag.getJahr());
        wJahrAnzahl.setText(String.valueOf(anzahlJahre));
        wJahrNachwort.setText(getString(
                R.string.nachwort,
                anzahlJahre,
                anzahlJahre == 1 ? getString(R.string.jahr):getString(R.string.jahre),
                anzahlJahre == 1 ? getString(R.string.datei):getString(R.string.dateien)
        ));
    }

    public void action(int action, Arbeitsplatz job, StorageHelper storageHelper){
        if(kStarttag != null) {
            exportSave(action, job, storageHelper);
        }
    }


    /*
     * eine Checkbox für optionale Zusatzeinträge wurde ein- oder ausgeschaltet
     */
    @Override
    public void onButtonClick(int tabelle, boolean eingeschaltet) {
        BitSet bitSet;
        String key;
        if (tabelle < IExport_Basis.TAB_ZUSATZ) {
            bitSet = bsTabellen;
            key = KEY_EXP_J_TABELLEN;
        } else {
            tabelle -= IExport_Basis.TAB_ZUSATZ;
            bitSet = bsZusatzfelder;
            key = KEY_EXP_J_ZUSATZ;
        }
        if (bitSet.get(tabelle) != eingeschaltet) {
            bitSet.set(tabelle, eingeschaltet);

            int value = 0;
            for (int i = 0; i < bitSet.size(); ++i) {
                value += bitSet.get(i) ? (1 << i) : 0;
            }
            ASettings.mPreferenzen.edit().putInt(key, value).apply();
        }
    }

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

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

    // auf den Schalter für Unterschriften reagieren
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (buttonView.getId() == R.id.EJ_switch_unterschrift) {
            if (isChecked != bsOptionen.get(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT)) {
                bsOptionen.set(IExport_Basis.OPTION_ZEILE_UNTERSCHRIFT, 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_EXP_J_OPTIONEN, value).apply();
            }
            bUnterschriften.setVisibility(isChecked ? View.VISIBLE : View.GONE);
        }
    }


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

        // auszugebende Spalten
        //bsSpalten = new BitSet(IBasis.DEF_MAXBIT_SPALTE);
        mWert = ASettings.mPreferenzen.getInt(KEY_EXP_J_TABELLEN, IExport_Basis.DEF_TABELLEN);
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_TABELLEN; i++) {
            bsTabellen.set(i, (mWert & (1 << i)) != 0);
        }

        // die daktivierten Spalten
        bsTabellenDeaktiviert.set(0, IExport_Basis.DEF_MAXBIT_TABELLEN, false);


        // ist kein Stundenlohn hinterlegt, dann die Spalte deaktivieren
        if (ASettings.aktJob.getStundenlohn() <= 0) {
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_VERDIENST, true);
            bsTabellen.set(IExport_Basis.TAB_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
            bsTabellen.set(IExport_Basis.TAB_EINSATZORTE, false);
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_EINSATZORTE, true);
        }

        // wenn kein Urlaub berechnet wird (Urlaubsanspruch = 0,
        // dann die entsprechenden Spalten und Optionen deaktivieren
        if ( ASettings.aktJob.getSoll_Urlaub() <= 0
                || !ASettings.aktJob.getAbwesenheiten().isKategorie(Abwesenheit.KAT_URLAUB)
        ) {
            // es werden keine Einsatzorte erfasst
            // also werden entsprechende Option deaktiviert
            bsTabellen.set(IExport_Basis.TAB_URLAUB, false);
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_URLAUB, true);
        }

        // es gibt keine Abwesenheit mit der Kategorie "Urlaub"
        if(!ASettings.aktJob.getAbwesenheiten().isKategorie(Abwesenheit.KAT_URLAUB)){
            bsTabellen.set(IExport_Basis.TAB_URLAUB, false);
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_URLAUB, true);
        }

        // es gibt keine Abwesenheit mit der Kategorie "Unfall"
        if(!ASettings.aktJob.getAbwesenheiten().isKategorie(Abwesenheit.KAT_UNFALL)){
            bsTabellen.set(IExport_Basis.TAB_UNFALL, false);
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_UNFALL, true);
        }

        // es gibt keine Abwesenheit mit der Kategorie "Krank"
        if(!ASettings.aktJob.getAbwesenheiten().isKategorie(Abwesenheit.KAT_KRANK)){
            bsTabellen.set(IExport_Basis.TAB_KRANK, false);
            bsTabellenDeaktiviert.set(IExport_Basis.TAB_KRANK, true);
        }

        // noch gibt es keine Tabelle mit Schwellwerten
        bsTabellen.set(IExport_Basis.TAB_SCHWELLEN, false);
        bsTabellenDeaktiviert.set(IExport_Basis.TAB_SCHWELLEN, true);

        // auszugebende Zeilen und optionale Tabellen, Zusätze
        //bsOptionen = new BitSet(IBasis.DEF_MAXBIT_OPTION);
        mWert = ASettings.mPreferenzen.getInt(KEY_EXP_J_OPTIONEN, IExport_Basis.DEF_OPTIONEN);
        for (int i = 0; i <= IExport_Basis.DEF_MAXBIT_OPTION; i++) {
            bsOptionen.set(i, (mWert & (1 << i)) != 0);
        }
        bsOptionen.set(IExport_Basis.OPTION_ALL_JOBS, false);

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


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

        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 berichtJahr = new Datum(kStarttag);
            boolean mStatus = true;
            ArrayList<String> mDateinamen = new ArrayList<>();

            for (int i = 0; i < anzahlJahre; i++) {
                if (exportDateityp == IExport_Basis.TYP_CSV) {
                    Export_CSV_Jahr mCSVJahr;
                    try {
                        mCSVJahr = new Export_CSV_Jahr(
                                mContext,
                                job,
                                berichtJahr.getTimeInMillis(),
                                storageHelper,
                                bsTabellen,
                                bsZusatzfelder
                        );
                        mDateinamen.add(mCSVJahr.getDateiName());
                    } catch (Exception e) {
                        e.printStackTrace();
                        mStatus = false;
                    }
                } else {
                    exportDateityp = IExport_Basis.TYP_PDF;
                    Export_PDF_Jahr mPDFJahr;
                    try {
                        mPDFJahr = new Export_PDF_Jahr(
                                mContext,
                                new Zeitraum_Jahr(
                                        new Arbeitsjahr_summe(
                                                berichtJahr.get(Calendar.YEAR),
                                                job)),
                                bsOptionen,
                                bsTabellen,
                                bsZusatzfelder,
                                storageHelper);
                        mDateinamen.add(mPDFJahr.getDateiName());
                    } catch (Exception e) {
                        e.printStackTrace();
                        mStatus = false;
                    }
                }
                berichtJahr.add(Calendar.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_JAHR,
                            fDateinamen,
                            kStarttag,
                            null);
                }
            });

        }).start();
    }
}