/* 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 android.net.Uri;
import android.provider.DocumentsContract;

import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.BitSet;

import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.StorageHelper;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.IZusatzfeld;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.ZusatzfeldDefinition;

public abstract class AExportBasis implements IExport_Basis {
    Context mContext;
    //String mPfad;
    String mDateiname;
    OutputStream mDatei;
    StorageHelper mStorageHelper;

    AExportBasis(Context context) {
        mContext = context;
    }

    // Tabelle ausgeben
    public void schreibeTabelle(
            @NonNull StorageHelper storageHelper,
            @NonNull  String dateiname,
            int dateityp
    ) throws Exception {
        mStorageHelper = storageHelper;
        String post = "";
        String mimeTyp = "";

        switch (dateityp) {
            case TYP_PDF:
                post = mContext.getString(R.string.post_pdf);
                mimeTyp = DATEI_TYP_PDF;
                break;
            case TYP_CSV:
                post = mContext.getString(R.string.post_csv);
                mimeTyp = DATEI_TYP_CSV;
                break;
            case TYP_CAL_ICS:
                post = mContext.getString(R.string.post_ics);
                mimeTyp = DATEI_TYP_ICS;
                break;
        }

        Uri docUri = null;
        if (storageHelper.isExists()){
            mDateiname = makeDateiname(dateiname, post);
            docUri = DocumentsContract.createDocument(
                    mContext.getContentResolver(),
                    storageHelper.getVerzeichnisFile().getUri(),
                    mimeTyp,
                    mDateiname
            );

            if (docUri != null) {
                //mDateiname = oDatei.getName();
                mDatei = mContext.getContentResolver().openOutputStream(docUri);
                // die Tabelle schreiben
                if (mDatei != null) {
                    // Ausgabestream öffnen
                    oeffneAusgabe();
                    // Seite schreiben
                    schreibeSeiten();
                    // Ausgabestream schliessen
                    schliesseAusgabe();
                    // Datei schliessen
                    try {
                        mDatei.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                throw new Exception("Outputstream konnte nicht geffnet werden.");
            }
        }
    }

    // gibt den Dateipfad zurück
    public String getDateiName(){
        return mDateiname;
    }

    // erzeugt eine Liste aller Spalten
    // wenn der Wert isForDialog == false dann werden die nicht gesetzten Spalten ausgeblendet
    @Override
    public ArrayList<Spalte> makeSpaltenSet(
            BitSet spalten,
            BitSet zusatzwerte,
            Arbeitsplatz arbeitsplatz){
        ArrayList<Spalte> listSpalten = new ArrayList<>();
        String[] namen = ASettings.res.getStringArray(R.array.export_spalten);
        int spalteNetto = 0;
        int spalteVerdienst = 0;
        boolean isText;

        // die regulären Spalten
        for (int s = 0; s <= IExport_Basis.DEF_MAXBIT_SPALTE; s++){
            if(spalten.get(s)){
                isText = s==SPALTE_DATUM ||
                        s==SPALTE_EORT ||
                        s==SPALTE_SCHICHTNAME ||
                        s==SPALTE_ANGELEGT ||
                        s==SPALTE_AENDERUNG;
                listSpalten.add(new Spalte(s, namen[s], isText));
                if(s == IExport_Basis.SPALTE_NETTO){
                    spalteNetto = listSpalten.size()-1;
                } else if(s == IExport_Basis.SPALTE_VERDIENST){
                    spalteVerdienst = listSpalten.size()-1;
                }
            }
        }

        // die Zusatzwerte
        for(int z=0; z<arbeitsplatz.getZusatzfeldListe().size(); z++){
            if(zusatzwerte.get(z)) {
                ZusatzfeldDefinition zDef = arbeitsplatz.getZusatzDefinition(z);
                if (zDef != null) {
                    int s = IExport_Basis.SPALTE_ZUSATZ + z;
                    switch (zDef.getWirkung()) {
                        case IZusatzfeld.ADD_VERDIENST:
                        case IZusatzfeld.SUB_VERDIENST:
                            if (spalteVerdienst > 0) {
                                listSpalten.add(spalteVerdienst, new Spalte(s, zDef.getName(), false));
                            } else {
                                listSpalten.add(new Spalte(s, zDef.getName(), false));
                            }
                            break;
                        case IZusatzfeld.ADD_ISTSTUNDEN:
                        case IZusatzfeld.SUB_ISTSTUNDEN:
                        case IZusatzfeld.SUB_SOLLSTUNDEN:
                            if (spalteNetto > 0) {
                                listSpalten.add(spalteNetto, new Spalte(s, zDef.getName(), false));
                            } else {
                                listSpalten.add(new Spalte(s, zDef.getName(), false));
                            }
                            if (spalteVerdienst > 0){
                                spalteVerdienst ++;
                            }
                            break;
                        default:
                            listSpalten.add(new Spalte(s,
                                    zDef.getName(),
                                    (zDef.getTyp() == IZusatzfeld.TYP_TEXT ||
                                     zDef.getTyp() == IZusatzfeld.TYP_AUSWAHL_TEXT)
                                    ));
                    }
                }
            }
        }

        return listSpalten;
    }





    /*
     * Eine Spalte wird durch ihren Name und die Position innerhalb der Tabelle gekennzeichnet
     */
    public static class Spalte{
        String mName;   //Spaltenname
        int mSpalte;    //Spaltenwert z.B. Datum, Saldo, Monat etc
        boolean isText;

        Spalte(int nummer, String name, boolean istext){
            mSpalte = nummer;
            mName = name;
            isText = istext;
        }
    }



    /*
     * Wenn die Datei schon existiert, dann einen Nummer anhängen
     */
    private String makeDateiname(String dateiname, String post) {
        StringBuilder mFileName = new StringBuilder(dateiname + post);

        DocumentFile ordner = mStorageHelper.getVerzeichnisFile();

        if(ordner!= null && ordner.exists()) {
            int mNummer = 0;
            int mIndexOfNummer = mFileName.lastIndexOf(".");

            // prüfen ob Datei schon vorhanden ist
            DocumentFile datei = ordner.findFile(mFileName.toString());

            while (datei != null && datei.exists()) {
                //Datei ist bereits vorhanden
                //Dateiname um (nNummer) erweitern
                mNummer++;
                if (mNummer == 1) {
                    mFileName.insert(mIndexOfNummer, "(1)");
                    mIndexOfNummer++; // zeigt nun auf "("
                } else {
                    // Dateinummer austauschen
                    mFileName.replace(
                            mIndexOfNummer,
                            mFileName.lastIndexOf(")"),
                            String.valueOf(mNummer));
                }
                // prüfen ob Datei schon vorhanden ist
                datei = ordner.findFile(mFileName.toString());
            }
        }

        // Dateityp Kürzel löschen, wird beim erzeugen automatisch angehängt
        //mFileName.delete(mFileName.lastIndexOf("."), mFileName.length());
        return mFileName.toString();
    }


    // Gibt den ersten Teil des Dateinamens zurück. Der ist immer gleich <Username>_<Jobname>_
    public static String getBasisDateiname(/*Context ctx*/) {
        return ASettings.res.getString(
                R.string.exp_basis_dateiname,
                ASettings.mPreferenzen.getString(ISettings.KEY_USERNAME, "").replaceAll(ASettings.REG_EX_PFAD, "_"),
                ASettings.aktJob.getName().replaceAll(ASettings.REG_EX_PFAD, "_"));
    }
}
