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

import com.pdfjet.Align;
import com.pdfjet.Cell;
import com.pdfjet.Table;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import askanimus.arbeitszeiterfassung2.StorageHelper;
import askanimus.arbeitszeiterfassung2.Zeitraum.IZeitraum;
import askanimus.arbeitszeiterfassung2.Zeitraum.Zeitraum_Jahr;
import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.abwesenheiten.AbwesenheitListe;
import askanimus.arbeitszeiterfassung2.arbeitsschicht.SchichtListeJahr;
import askanimus.arbeitszeiterfassung2.arbeitsjahr.Arbeitsjahr_summe;
import askanimus.arbeitszeiterfassung2.arbeitsmonat.Arbeitsmonat;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitstag.Arbeitstag;
import askanimus.arbeitszeiterfassung2.Datum;
import askanimus.arbeitszeiterfassung2.einsatzort.Einsatzort;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.Uhrzeit;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.ZusatzWertListe;

/**
 * @author askanimus@gmail.com on 10.01.16.
 */
public class Export_PDF_Jahr extends AExportBasis_PDF {
    private ArrayList<TabellenArbeitsplatz> mTabellen;
    private IZeitraum mZeitraum;
    private ArrayList<Arbeitsplatz> mArbeitsplatzListe;
    private Arbeitsplatz mArbeitsplatz;
    private BitSet bsOptionen;
    private int mSpalten;
    private BitSet bsTabellen;
    private BitSet bsZusatzwerte;
    boolean isDezimal;
    Arbeitsjahr_summe mJahr;


    Export_PDF_Jahr(
            Context context,
            IZeitraum zeitraum,
            BitSet optionen,
            BitSet tabellen,
            BitSet zusatzwerte,
            StorageHelper storageHelper
    ) throws Exception {
        super(context);
        mTabellen = new ArrayList<>(); // alle Tabellen aller Arbeitsplätze
        mZeitraum = zeitraum;
        //mJahr = ((Zeitraum_Jahr)mZeitraum).mArbeitsjahr;
        //mSpalten = new BitSet(mJahr.getAnzahlMonate()+2);
        bsZusatzwerte = zusatzwerte;
        bsOptionen = optionen;
        bsTabellen = tabellen;
        //farbeHintergrund = false;

        if (bsOptionen.get(OPTION_ALL_JOBS)) {
            mArbeitsplatzListe = ASettings.jobListe.getListe();
        } else {
            mArbeitsplatzListe = new ArrayList<>();
            mArbeitsplatzListe.add(mZeitraum.getArbeitsplatz());
        }
        // den Dateiname zusammenstellen
        //String dateiname = mZeitraum.getDateiname(context, 0);
        //dateiname = ExportActivity.makeExportpfad(context, pfad, dateiname);

        setupSeite(
                TABTYP_JAHR,
                bsOptionen,
                //false,
                zeitraum.getTitel(context),
                null,
                "",
                zeitraum.getPDFFontSize()
                );

        schreibeTabelle(
                storageHelper,
                mZeitraum.getDateiname(context, 0),
                TYP_PDF
        );
    }


    @Override
    public ArrayList<TabellenArbeitsplatz> erzeugeTabellen() throws Exception {
        TabellenArbeitsplatz mTabellenArbeitsplatz; // die Tabellen eines Arbeitsplatzes

        for (int i = 0; i < mArbeitsplatzListe.size(); i++) {
            mArbeitsplatz = mArbeitsplatzListe.get(i);
            if (i > 0) {
                mZeitraum = mZeitraum.wechselArbeitsplatz(mArbeitsplatz);
            }
            mJahr = ((Zeitraum_Jahr) mZeitraum).getArbeitsjahr();
            mSpalten = mJahr.getAnzahlMonate() + 2;
            isDezimal = mArbeitsplatz.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL);


            // neuen Tabellensatz für diesen Arbeitsplatz anlegen
            mTabellenArbeitsplatz = new TabellenArbeitsplatz();
            mTabellenArbeitsplatz.arbeitsplatz = mArbeitsplatz;

            // Haupttabelle erzeugen
            mTabellenArbeitsplatz.multitabelle = new ArrayList<>();

            // alle Teiltabellen erzeugen
            makeTabellen(mTabellenArbeitsplatz.multitabelle);
            // weitere optionale Tabellen anlegen

            // den Tabellensatz des Arbeitsplatzes speichern
            mTabellen.add(mTabellenArbeitsplatz);
        }
        return mTabellen;
    }


    // Tabelle zusammenstellen
    private  void makeTabellen(ArrayList<Table> tabellen) throws Exception{
        Table tabelle;
        // Arbeitsstunden
        if(bsTabellen.get(TAB_ARBEITSZEIT)) {
            tabelle = tabelleStunden();
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Arbeitstage
        if(bsTabellen.get(TAB_ARBEITSTAGE)) {
            tabelle = tabelleTage();
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // abwesenheiten
        if(bsTabellen.get(TAB_ABWESENHEITEN)) {
            tabelle = tabelleAbwesenheiten();
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Sonstige Werte
        tabelle = tabelleZusatzwerte();
        if(tabelle != null) {
            tabellen.add(tabelle);
        }
        /*makeLeerzeile(tableData, mSpalten, true);
          tabelleZusatzwerte(tableData);*/

        // Urlaub
        if(bsTabellen.get(TAB_URLAUB)) {
            tabelle = tabelleUrlaub();
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Krank
        if(bsTabellen.get(TAB_KRANK)) {
            tabelle = tabelleKategorie(
                    Abwesenheit.KAT_KRANK, mContext.getString(R.string.krank)
            );
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Unfall
        if(bsTabellen.get(TAB_UNFALL)) {
            tabelle = tabelleKategorie(
                    Abwesenheit.KAT_UNFALL, mContext.getString(R.string.unfall)
            );
            if(tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Einsatzorte
        if(bsTabellen.get(TAB_EINSATZORTE)) {
            tabelle = tabelleEinsatzort();
            if (tabelle != null) {
                tabellen.add(tabelle);
            }
        }

        // Schichten
        if(bsTabellen.get(TAB_SCHICHTEN)) {
            tabelle = tabelleSchichten();
            if (tabelle != null) {
                tabellen.add(tabelle);
            }
        }
    }

    // Teiltabelle - Arbeitszeit
    private Table  tabelleStunden() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();

        // Überschrift
        makeTabellenTitel(tableData, ASettings.res.getString(R.string.arbeitsstunden));

        // Kopfzeile
        makeTabellenKopf(tableData);

        // Datenzeilen
        // Kopfspalte
        List<Cell> rowSoll = new ArrayList<>();
        List<Cell> rowIst = new ArrayList<>();
        List<Cell> rowDiff = new ArrayList<>();
        List<Cell> rowVormonat = new ArrayList<>();
        List<Cell> rowAusbezahlt = new ArrayList<>();
        List<Cell> rowSaldo = new ArrayList<>();

        rowSoll.add(makeZelleKopf(ASettings.res.getString(R.string.soll)));
        rowSoll.get(0).setBgColor(cGrau);
        rowIst.add(makeZelleKopf(ASettings.res.getString(R.string.ist)));
        rowDiff.add(makeZelleKopf(ASettings.res.getString(R.string.diff)));
        rowDiff.get(0).setBgColor(cGrau);
        rowVormonat.add(makeZelleKopf(ASettings.res.getString(R.string.saldo_vm)));
        rowAusbezahlt.add(makeZelleKopf(ASettings.res.getString(R.string.ueberstunden_ausbezahlt)));
        rowAusbezahlt.get(0).setBgColor(cGrau);
        rowSaldo.add(makeZelleKopf(ASettings.res.getString(R.string.saldo)));

        //Monate
        for (int i = 0; i < mJahr.getAnzahlMonate(); i++) {
            rowSoll.add(makeZelleStunden(
                    mJahr.getArbeitszeitSollMonat(i), isDezimal, false, true));

            rowIst.add(makeZelleStunden(
                    mJahr.getArbeitszeitIstMonat(i), isDezimal, true, false));

            rowDiff.add(makeZelleStunden(
                    mJahr.getArbeitszeitDiffMonat(i), isDezimal, false, true));

            rowVormonat.add(makeZelleStunden(
                    mJahr.getArbeitszeitSaldoVormonat(i), isDezimal, false, false));

            rowAusbezahlt.add(makeZelleStunden(
                    mJahr.getArbeitszeitAusbezahltMonat(i), isDezimal, false, true));

            rowSaldo.add(makeZelleSummeStunden(
                    mJahr.getArbeitszeitSaldoMonat(i), isDezimal, false, true));
        }

        // Summenspalte
        rowSoll.add(makeZelleSummeStunden(
                mJahr.getSoll(), isDezimal, false, false));

        rowIst.add(makeZelleSummeStunden(
                mJahr.getIst(), isDezimal, false, false));

        rowDiff.add(makeZelleSummeStunden(
                mJahr.getDifferenz(), isDezimal, false, false));

        rowVormonat.add(makeZelleSummeStunden(
                mJahr.getSaldoVorjahr(), isDezimal, false, false));

        rowAusbezahlt.add(makeZelleSummeStunden(
                mJahr.getAusgezahlt(), isDezimal, false, false));

        rowSaldo.add(makeZelleSummeStunden(
                mJahr.getSaldo(), isDezimal, false, true));

        // Zeilen zur Tabelle hinzu fügen
        tableData.add(rowSoll);
        tableData.add(rowIst);
        tableData.add(rowDiff);
        tableData.add(rowVormonat);
        tableData.add(rowAusbezahlt);
        tableData.add(rowSaldo);

        return makeTabelle(
                tableData,
                Table.DATA_HAS_2_HEADER_ROWS,
                false,
                null
        );
    }

    // Teiltabelle - Arbeitstage
    private Table tabelleTage() throws Exception {
        List<List<Cell>> tableData = new ArrayList<>();

        // Überschrift
        makeTabellenTitel(tableData, ASettings.res.getString(R.string.arbeitstage));

        // Kopfzeile
        makeTabellenKopf(tableData);

        // Datenzeilen

        // Kopfspalte
        List<Cell> rowSoll = new ArrayList<>();
        List<Cell> rowIst = new ArrayList<>();
        List<Cell> rowDiff = new ArrayList<>();

        rowSoll.add(makeZelleKopf(ASettings.res.getString(R.string.soll)));
        rowSoll.get(0).setBgColor(cGrau);
        rowIst.add(makeZelleKopf(ASettings.res.getString(R.string.ist)));
        rowDiff.add(makeZelleKopf(ASettings.res.getString(R.string.diff)));
        rowDiff.get(0).setBgColor(cGrau);

        //Monate
        float mSoll;
        float mIst;
        float mSummeSoll = 0;
        float mSummeIst = 0;
        for (int i = 0; i < mJahr.getAnzahlMonate(); i++) {
            mSoll = (mJahr.listMonate.get(i)).getSollArbeitsTage(true);
            mIst = (mJahr.listMonate.get(i)).getSummeKategorieTage(Abwesenheit.KAT_ARBEITSZEIT);
            mSummeSoll += mSoll;
            mSummeIst += mIst;
            rowSoll.add(makeZelleWert(mSoll, ASettings.zahlenformat, true));
            rowIst.add(makeZelleWert(mIst, ASettings.zahlenformat, false));
            mIst -= mSoll;
            rowDiff.add(makeZelleWert(mIst, ASettings.zahlenformat, true));
        }

        // Summenspalte
        rowSoll.add(makeZelleSummeWert( mSummeSoll, ASettings.zahlenformat, false));

        rowIst.add(makeZelleSummeWert(mSummeIst, ASettings.zahlenformat, false));

        mSummeIst -= mSummeSoll;
        rowDiff.add(makeZelleSummeWert(mSummeIst, ASettings.zahlenformat, true));


        // Zeilen zur Tabelle hinzu fügen
        tableData.add(rowSoll);
        tableData.add(rowIst);
        tableData.add(rowDiff);

        return makeTabelle(
                tableData,
                Table.DATA_HAS_2_HEADER_ROWS,
                false,
                null
        );
    }

    // Teiltabelle - abwesenheiten
    private Table tabelleAbwesenheiten() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();
        boolean farbeHintergrund = true;
        /*Uhrzeit Stunden = new Uhrzeit(0);
        Uhrzeit SummeStunden = new Uhrzeit(0);*/
        float mTage = 0;
        //float mSummeTage = 0;

        // Überschrift
        makeTabellenTitel(tableData, ASettings.res.getString(R.string.summe_tage));

        // Kopfzeile
        makeTabellenKopf(tableData);

        List<Cell> mZeile;
        ArrayList<Float> mAbwesenheit;

        for (int a = 0; a < mJahr.getAbwesenheiten().get(mJahr.INDEX_SUMME).size(); a++) {
            mZeile = new ArrayList<>();
            //List<Cell> mZusatzzeile = new ArrayList<>();
            mAbwesenheit = mJahr.getAbwesenheitMonate(a);

            if( mAbwesenheit.get(mJahr.INDEX_SUMME) > 0) {
                Abwesenheit aw = mArbeitsplatz.getAbwesenheiten().get(a);
                //int awWirkung = aw.getWirkung();

                mZeile.add(makeZelleKopf(aw.getName()));
                mZeile.get(0).setBgColor(farbeHintergrund?cGrau:cLeer);
                /*if(
                        awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_EFFEKTIV ||
                        awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_PAUSCHAL){
                    mZusatzzeile.add(makeZelleLeer(farbeHintergrund));
                }*/
                for (int m = 1; m <= mJahr.getAnzahlMonate(); m++){
                    mTage = mJahr.listMonate.get(m-1).getSummeAlternativTage(aw.getID());
                    //mSummeTage += mTage;
                    mZeile.add(makeZelleWert(mTage, ASettings.zahlenformat, farbeHintergrund));

                    /*if(awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_EFFEKTIV){
                        Stunden.set((mJahr.listMonate.get(m-1)).getSummeAlternativMinuten(aw.getID()));
                        SummeStunden.add(Stunden.getAlsMinuten());
                    } else if(awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_PAUSCHAL){
                        Stunden.set(Math.round(mAbwesenheit.get(m) * mArbeitsplatz.getTagSollPauschal()));
                        SummeStunden.add(Stunden.getAlsMinuten());
                    }
                    mZeile.add(makeZelleWert(Stunden.getAlsDezimalZeit(), Einstellungen.tageformat, farbeHintergrund));*/
                }

                mZeile.add(makeZelleSummeWert(mAbwesenheit.get(mJahr.INDEX_SUMME), ASettings.zahlenformat, true));
                /*if(awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_EFFEKTIV || awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_PAUSCHAL){
                        mZusatzzeile.add(makeZelleString(
                                "(" + SummeStunden.getStundenString(true, isDezimal) + ")",
                                farbeHintergrund )
                        );
                        //mZeile.get(mZeile.size()-1).setText(mZeile.get(mZeile.size()-1).getText() + "\n" + SummeStunden.getStundenString(true, isDezimal));
                        SummeStunden.set(0);
                } else if(awWirkung == Einstellungen.ABW_WIRKUNG_IST_PLUS_PAUSCHAL){
                        mZeile.get(mZeile.size()-1).setText(mZeile.get(mZeile.size()-1).getText() + "\n" + SummeStunden.getStundenString(true, isDezimal));
                        SummeStunden.set(0);
                }*/
                tableData.add(mZeile);
                /*if(mZusatzzeile.size() > 0){
                   tableData.add(mZusatzzeile);
                }*/
                farbeHintergrund = !farbeHintergrund;
            }
        }
        farbeHintergrund = false;

        return makeTabelle(
                tableData,
                Table.DATA_HAS_2_HEADER_ROWS,
                false,
                null
        );
    }

    // Teiltabelle - Zusatzwerte
    private Table tabelleZusatzwerte() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();
        boolean farbeHintergrund = true;

        List<List<Cell>> zeilenZusatzwerte = new ArrayList<>();

        ZusatzWertListe zusatzwerteListe = mJahr.mZusatzwerteJahresSumme;
        for (int zf = 0; zf < zusatzwerteListe.size(); zf++) {
            if (bsZusatzwerte.get(zf)) {
                //ZusatzfeldDefinition zfDefinition = zusatzwerteListe.get(zf).getDefinition();
                List<Cell> zeile = new ArrayList<>();
                // den Zeilenkopf mit dem Namen des Eintrags erstellen
                zeile.add(makeZelleKopf(zusatzwerteListe.get(zf).getName()));
                zeile.get(0).setBgColor(farbeHintergrund ? cGrau : cLeer);

                // die Monatswerte des Eintrages in der Zeile eintragen
                for (int m = 0; m < mJahr.listMonate.size(); m++) {
                    zeile.add(makeZelleZusatzwert(
                            mJahr.mZusazwerteMonatsSummen.get(m).get(zf),
                            isDezimal,
                            farbeHintergrund,
                            false));
                }
                    /*for (Arbeitsmonat monat : mJahr.listMonate) {
                        zeile.add(makeZelleZusatzwert(
                                monat.getSummeZusatzeintrag(zf),
                                isDezimal,
                                farbeHintergrund,
                                false));
                    }*/

                // die Summenzelle erzeugen
                zeile.add(makeZelleSummeZusatzwert(
                        zusatzwerteListe.get(zf),
                        isDezimal));

                // die Hintergrundfarbe wechseln
                farbeHintergrund = !farbeHintergrund;

                // die Zeile in die Tabelle übertragen
                zeilenZusatzwerte.add(zeile);
                // }
            }
        }

        if(zeilenZusatzwerte.size() > 0) {
            // Überschrift
            makeTabellenTitel(tableData, ASettings.res.getString(R.string.sonstige));

            // Kopfzeile
            makeTabellenKopf(tableData);

            // die erzeugten Tabellen einfügen
            tableData.addAll(zeilenZusatzwerte);
            return makeTabelle(
                    tableData,
                    Table.DATA_HAS_2_HEADER_ROWS,
                    false,
                    null
            );
        }
        return null;
    }

    // Teiltabelle - Urlaub
    private Table tabelleUrlaub() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();
        float mUrlaub = mJahr.getUrlaubSoll();
        float mResturlaub = mJahr.getResturlaub();
        boolean inStunden = mArbeitsplatz.isOptionSet(Arbeitsplatz.OPT_URLAUB_ALS_STUNDEN);
        //float tagSollStunden = mArbeitsplatz.getTagSollPauschal();

        // Überschrift
        makeTabellenTitel(
                tableData,
                String.format(
                        ASettings.res.getString(R.string.exp_titel_urlaub),
                        mZeitraum.getBeginn().get(Calendar.YEAR) - 1,
                        inStunden ?
                                ASettings.stundenformat.format(mJahr.getResturlaub()) :
                                ASettings.tageformat.format(mJahr.getResturlaub()),
                        mZeitraum.getBeginn().get(Calendar.YEAR),
                        inStunden ?
                                ASettings.stundenformat.format(mJahr.getResturlaub()) :
                                ASettings.tageformat.format(mJahr.getUrlaubSoll()))
        );

        // Kopfzeile
        makeTabellenKopf(tableData);

        // die Zeilen
        // List<Cell> zRestAnspruch = new ArrayList<>();
        List<Cell> zRestBezogen = new ArrayList<>();
        List<Cell> zRestSaldo = new ArrayList<>();
        //List<Cell> zAnspruch = new ArrayList<>();
        List<Cell> zBezogen = new ArrayList<>();
        List<Cell> zSaldo = new ArrayList<>();

        // die Zeilenköpfe
        //zRestAnspruch.add(new Cell(pdfSeite.fKopf, Einstellungen.res.getString(R.string.resturlaub)));
        zRestBezogen.add(makeZelleKopf(ASettings.res.getString(R.string.abgebaut)));
        zRestBezogen.get(0).setBgColor(cGrau);
        zRestSaldo.add(makeZelleKopf(ASettings.res.getString(R.string.rest)));
        //zAnspruch.add(new Cell(pdfSeite.fKopf, Einstellungen.res.getString(R.string.anspruch)));
        zBezogen.add(makeZelleKopf(ASettings.res.getString(R.string.bezogen)));
        zBezogen.get(0).setBgColor(cGrau);
        zSaldo.add(makeZelleKopf(ASettings.res.getString(R.string.saldo)));

        // die Monate
        int i;
        for (Object m : mJahr.listMonate) {
            Arbeitsmonat mMonat = (Arbeitsmonat) m;
            i = mMonat.getMonat();


            // Abgebauter Resturlaub
            zRestBezogen.add(makeZelleWert(
                    mJahr.bezogenRest[i],
                    inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                    true));

            mResturlaub -= mJahr.bezogenRest[i];

            // noch vorhandener Resturlaub
            zRestSaldo.add(makeZelleWert(
                    mResturlaub,
                    inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                    false));

            if (mResturlaub > 0 && mJahr.isUrlaubVerfallen(i))
                zRestSaldo.get(zRestBezogen.size() - 1).setStrikeout(true);

            // Urlaub bezogen
            zBezogen.add(makeZelleWert(
                    mJahr.bezogenUrlaub[i],
                    inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                    true));

            // noch nicht bezogener Urlaub
            mUrlaub -= mJahr.bezogenUrlaub[i];
            zSaldo.add(makeZelleWert(
                    mUrlaub,
                    inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                    false));


            /*if (inStunden) {
                int h = Math.round(tagSollStunden * mJahr.bezogenRest[i]);
                zRestBezogen.add(makeZelleStunden(h, isDezimal, false, true));
            } else {
                zRestBezogen.add(makeZelleWert(mJahr.bezogenRest[i], ASettings.zahlenformat, true));
            }

            mResturlaub -= mJahr.bezogenRest[i];
            if (inStunden) {
                int h = Math.round(tagSollStunden * mResturlaub);
                zRestSaldo.add(makeZelleStunden(h, isDezimal, false, false));
            } else {
                zRestSaldo.add(makeZelleWert(mResturlaub, ASettings.zahlenformat, false));
            }
            if (mResturlaub > 0 && mJahr.isUrlaubVerfallen(i))
                zRestSaldo.get(zRestBezogen.size() - 1).setStrikeout(true);

            if (inStunden) {
                int h = Math.round(tagSollStunden * mJahr.bezogenUrlaub[i]);
                zBezogen.add(makeZelleStunden(h, isDezimal, false, true));
            } else {
                zBezogen.add(makeZelleWert(mJahr.bezogenUrlaub[i], ASettings.zahlenformat, true));
            }

            mUrlaub -= mJahr.bezogenUrlaub[i];
            if (inStunden) {
                int h = Math.round(tagSollStunden * mUrlaub);
                zSaldo.add(makeZelleStunden(h, isDezimal, false, false));
            } else {
                zSaldo.add(makeZelleWert(mUrlaub, ASettings.zahlenformat, false));
            }*/
        }

        // die Summen Spalte
        // Abgebauter Resturlaub
        zRestBezogen.add(makeZelleSummeWert(
                mJahr.getResturlaubIst(),
                //inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                ASettings.zahlenformat,
                true));

        // noch vorhandener Resturlaub
        zRestSaldo.add(makeZelleSummeWert(
                mResturlaub,
                //inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                ASettings.zahlenformat,
                true));
        // ist der Resturlaub verfallen, dann durchstreichen
        if (mResturlaub > 0 && mJahr.isUrlaubVerfallen(
                (mJahr.listMonate.get(
                        mJahr.listMonate.size() - 1)).getMonat())) {
            zRestSaldo.get(zRestBezogen.size() - 1).setStrikeout(true);
        }
        // Urlaub bezogen
        zBezogen.add(makeZelleSummeWert(
                mJahr.getIstUrlaub(),
                //inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                ASettings.zahlenformat,
                true));
        // noch nicht bezogener Urlaub
        zSaldo.add(makeZelleSummeWert(
                mJahr.getUrlaubSaldo(),
                //inStunden ? ASettings.stundenformat : ASettings.zahlenformat,
                ASettings.zahlenformat,
                true));


        /*if (inStunden) {
            int h = Math.round(tagSollStunden * mJahr.getResturlaubIst());
            zRestBezogen.add(makeZelleSummeStunden(h, isDezimal, false, false));
        } else {
            zRestBezogen.add(makeZelleSummeWert(mJahr.getResturlaubIst(), ASettings.zahlenformat, false));
        }

        if (inStunden) {
            int h = Math.round(tagSollStunden * mResturlaub);
            zRestSaldo.add(makeZelleSummeStunden(h, isDezimal, false, false));
        } else {
            zRestSaldo.add(makeZelleSummeWert(mResturlaub, ASettings.zahlenformat, false));
        }

        if (mResturlaub > 0 && mJahr.isUrlaubVerfallen(
                (mJahr.listMonate.get(
                        mJahr.listMonate.size() - 1)).getMonat()))
            zRestSaldo.get(zRestBezogen.size() - 1).setStrikeout(true);

        if (inStunden) {
            int h = Math.round(tagSollStunden * mJahr.getIstUrlaub());
            zBezogen.add(makeZelleSummeStunden(h, isDezimal, false, false));
        } else {
            zBezogen.add(makeZelleSummeWert(mJahr.getIstUrlaub(), ASettings.zahlenformat, false));
        }
        if (inStunden) {
            int h = Math.round(tagSollStunden * mJahr.getUrlaubSaldo());
            zSaldo.add(makeZelleSummeStunden(h, isDezimal, false, true));
        } else {
            zSaldo.add(makeZelleSummeWert(mJahr.getUrlaubSaldo(), ASettings.zahlenformat, true));
        }*/

        // Zeilen in die Tabelle einfügen
        tableData.add(zRestBezogen);
        tableData.add(zRestSaldo);
        tableData.add(zBezogen);
        tableData.add(zSaldo);

        return makeTabelle(
                tableData,
                Table.DATA_HAS_3_HEADER_ROWS,
                false,
                null
        );
    }

    // Teiltabelle - Abwesenheit einer bestimmten Kategorie z.B.: krank, Unfall etc.
    private Table tabelleKategorie(int kategorie, String name) throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();

        boolean farbeHintergrund = true;
        ArrayList<ArrayList<Float>> wAbwesenheiten = mJahr.getAbwesenheiten();
        AbwesenheitListe mAbwesenheiten = mArbeitsplatz.getAbwesenheiten();
        //float mGesamt[] = new float[12];
        float[] mGesamt = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        float jGesamt = 0;

        // Überschrift
        makeTabellenTitel(tableData, name);

        // Kopfzeile
        makeTabellenKopf(tableData);

        // die Zeilen anlegen
        for (int a = 0; a < mAbwesenheiten.size(); a++) {
            if (mAbwesenheiten.get(a).getKategorie() == kategorie) {
                List<Cell> kAbwesenheit = new ArrayList<>();
                kAbwesenheit.add(makeZelleKopf(mAbwesenheiten.get(a).getName()));
                kAbwesenheit.get(0).setBgColor(farbeHintergrund ? cGrau : cLeer);
                for (int m = 1; m < wAbwesenheiten.size(); m++) {
                    if(a < wAbwesenheiten.get(m).size()){
                        kAbwesenheit.add(makeZelleWert(wAbwesenheiten.get(m).get(a), ASettings.zahlenformat, farbeHintergrund));
                        mGesamt[m - 1] += wAbwesenheiten.get(m).get(a);
                    } else {
                        kAbwesenheit.add(makeZelleWert(0, ASettings.zahlenformat, farbeHintergrund));
                    }
                }
                kAbwesenheit.add(makeZelleSummeWert(wAbwesenheiten.get(mJahr.INDEX_SUMME).get(a), ASettings.zahlenformat, false));
                tableData.add(kAbwesenheit);
                jGesamt += wAbwesenheiten.get(mJahr.INDEX_SUMME).get(a);
                farbeHintergrund = !farbeHintergrund;
            }
        }
        // die Summenzeile
        List<Cell> kGesamt = new ArrayList<>();
        kGesamt.add(makeZelleKopf(ASettings.res.getString(R.string.gesamt)));
        for (int m = 1; m < wAbwesenheiten.size(); m++) {
            kGesamt.add(makeZelleSummeWert(mGesamt[m-1], ASettings.zahlenformat, false));
        }
        kGesamt.add(makeZelleSummeWert(jGesamt, ASettings.zahlenformat, true));

        tableData.add(kGesamt);

        return makeTabelle(
                tableData,
                Table.DATA_HAS_2_HEADER_ROWS,
                false,
                null
        );
    }

    // Teiltabelle - Einsatzorte
    private Table tabelleEinsatzort() throws Exception {
        List<List<Cell>> tableData = new ArrayList<>();
        boolean farbeHintergrund = true;

        // die Zeilen anlegen
        // ein Monat pro Spalte und ein einsatzort pro Zeile
        // eine Spalte Gesamt

        // die Liste der Einsatzorte
        ArrayList<long[]> tabEorte = new ArrayList<>();
        int aLang = mJahr.listMonate.size()+2;
        // die aktiven Orte
        for (Einsatzort o : mArbeitsplatz.getEinsatzortListe().getAlle()) {
            long[] eOrt_Monate = new long[aLang];
            int m = 1;
            for (Arbeitsmonat monat:mJahr.listMonate) {
                int mMinuten = monat.getSummeEinsatzortMinuten(o.getId());
                if(mMinuten > 0){
                    eOrt_Monate[m] = mMinuten;
                    eOrt_Monate[aLang - 1] += mMinuten;
                }
                m ++;
            }
            if(eOrt_Monate[aLang-1] > 0) {
                eOrt_Monate[0] = o.getId();
                tabEorte.add(eOrt_Monate);
            }
        }

        // wurden Einsatzorte mit Schichten gefunden, dann die Tabelle erzeugen
        if(tabEorte.size() > 0) {
            // Überschrift
            makeTabellenTitel(tableData, mContext.getString(R.string.einsatzort));

            // Kopfzeile
            makeTabellenKopf(tableData);
            // die einzelnen Zeilen anlegen
            Uhrzeit uz = new Uhrzeit();
            for (long[] eOrt_Monate : tabEorte) {
                List<Cell> kEinsatzort = new ArrayList<>();
                kEinsatzort.add(
                        makeZelleKopf(
                                mArbeitsplatz.getEinsatzortListe().getOrt(eOrt_Monate[0]).getName()
                        ));
                kEinsatzort.get(0).setBgColor(farbeHintergrund ? cGrau : cLeer);

                for (int m = 1; m <= mJahr.listMonate.size(); m++) {
                    kEinsatzort.add(makeZelleStunden((int) eOrt_Monate[m], isDezimal, false, farbeHintergrund));
                }
                uz.set((int) eOrt_Monate[aLang - 1]);
                kEinsatzort.add(makeZelleSummeStunden((int) eOrt_Monate[aLang - 1], isDezimal, false, true));
                tableData.add(kEinsatzort);
                farbeHintergrund = !farbeHintergrund;
            }

            return makeTabelle(
                    tableData,
                    Table.DATA_HAS_2_HEADER_ROWS,
                    false,
                    null
            );
        }
        return null;
    }

    // Teiltabelle Anzahl der Schichten in Tagen
    private Table tabelleSchichten() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();
        boolean farbeHintergrund = true;
        // die Liste der verwendeten Schichten anlegen inkl. der gesmtwerte des Jahres
        SchichtListeJahr benutztSchichten = new SchichtListeJahr(mJahr);

        if(benutztSchichten.size() > 0) {
            // Überschrift
            makeTabellenTitel(tableData, mContext.getString(R.string.schichten));

            // Kopfzeile
            makeTabellenKopf(tableData);

            // die Tabelle einlesen
            // Die Schleife für die Zeilen (Schichten)
            for (SchichtListeJahr.Schicht mSchicht : benutztSchichten.getJahr()) {
                List<Cell> mZeile = new ArrayList<>();
                // die Bezeichnung der Schicht in die erste Spalte
                mZeile.add(makeZelleKopf(mSchicht.getName()));
                mZeile.get(0).setBgColor(farbeHintergrund?cGrau:cLeer);

                // Die Schleife für die Monate
                for (int i : mSchicht.getMonate()) {
                    mZeile.add(makeZelleWert(i, ASettings.zahlenformat, farbeHintergrund));
                }
                // Summenspalte erzeugen
                mZeile.add(makeZelleSummeWert(
                        mSchicht.getTageJahr(),
                        ASettings.zahlenformat,
                        true));

                // die tabelle schreiben
                tableData.add(mZeile);
                farbeHintergrund = !farbeHintergrund;
            }
            return makeTabelle(
                    tableData,
                    Table.DATA_HAS_2_HEADER_ROWS,
                    false,
                    null
            );
        }
        return null;
    }

    //Teiltabelle Schwellwerte erzeugen
    private Table tabelleSchwellwerte() throws Exception{
        List<List<Cell>> tableData = new ArrayList<>();

        // Überschrift
        makeTabellenTitel(tableData, mContext.getString(R.string.schwellwerte));

        // Kopfzeile
        makeTabellenKopf(tableData);

        // die Zeilen anlegen
        for (int m = 1; m < mJahr.listMonate.size(); m++) {
            //
            ArrayList<Arbeitstag> listeTage = ((Arbeitsmonat)mJahr.listMonate.get(m)).getTagListe();
            for (int t = 0; t < listeTage.size(); t++) {

            }
        }

        return makeTabelle(
                tableData,
                Table.DATA_HAS_2_HEADER_ROWS,
                false,
                null
        );
    }


    // den Tabellentitel zusammensetzen
    private void makeTabellenTitel(List<List<Cell>> tableData, String titel){
        // Überschrifft
        List<Cell> row = new ArrayList<>();
        row.add(makeZelleKopf(titel));
        for (int i = 1; i < mSpalten; i++) {
            row.add(makeZelleLeer(true));
        }
        row.get(0).setColSpan(mSpalten);
        row.get(0).setTextAlignment(Align.CENTER);

        tableData.add(row);
    }

    // den Tabellenkopf zusammensetzen
    public void makeTabellenKopf(List<List<Cell>> tableData) {
        Datum mKal = new Datum(mZeitraum.getBeginn());
        List<Cell> row = new ArrayList<>();

        // Formater für Monatsname
        DateFormat fMonat;
        if(bsOptionen.get(OPTION_LAYOUT_QUEER)) {
            fMonat = new SimpleDateFormat("MMMM", Locale.getDefault());
        } else {
            fMonat = new SimpleDateFormat("MMM", Locale.getDefault());
        }

        row.add(makeZelleLeer(false));
        while (!mKal.liegtNach(mZeitraum.getEnde())) {
            row.add(makeZelleKopf(fMonat.format(mKal.getDate())));
            mKal.add(Calendar.MONTH, 1);
        }
        row.add(makeZelleKopf( ASettings.res.getString(R.string.gesamt)));
        tableData.add(row);
    }
}
