/*
 * Copyright (c) 2014 - 2024 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.stempeluhr;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.SharedPreferences;
import android.database.Cursor;

import androidx.annotation.NonNull;

import java.util.ArrayList;

import askanimus.arbeitszeiterfassung2.Datum;
import askanimus.arbeitszeiterfassung2.Uhrzeit;
import askanimus.arbeitszeiterfassung2.abwesenheiten.Abwesenheit;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitsschicht.SchichtDefault;
import askanimus.arbeitszeiterfassung2.datenbank.DatenbankHelper;
import askanimus.arbeitszeiterfassung2.einsatzort.Einsatzort;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.widget.WidgetStatus;
import askanimus.arbeitszeiterfassung2.zusatzeintrag.IZusatzfeld;

public class StempeluhrStatus extends WidgetStatus implements ISettings {
    public final static String KEY_STEMPELUHR_ID = "stempeluhr_id";
    public final static String KEY_STEMPELUHR_AKTION = "stempeluhr_action";
    public static final String START_PAUSE_CLICKED = "stempeluhr_start_pause";
    public static final String STOP_CLICKED = "stempeluhr_stop";

    private final static String SQL_READ_STATUS =
            "select *"
                    + " from " + DatenbankHelper.DB_T_STEMPELUHR_STATUS
                    + " where " + DatenbankHelper.DB_F_JOB + " = ? "
                    + " limit 1";
    private final String SQL_READ_ZUSAETZE =
                "select * from "
                        + DatenbankHelper.DB_T_STEMPELUHR_ZUSATZWERT
                        + " where "
                        + DatenbankHelper.DB_F_STEMPELUHR_STATUS
                        + " = ?";

    // dieser Zusatz wird an die Widget Schlüssel in den Preferenzen angehängt,
    // um diese von den Widget IDs zu unterscheiden
    protected static final String ZUSATZ = "SU_";

    long dbId = -1;
    private int listPosition;
    //ergänzende Werte für die Stempeluhr
    private SchichtDefault mSchichtdefault;
    private String mSchichtname;
    private Abwesenheit mAbwesenheit;
    private Einsatzort mEinsatzort;

    private ArrayList<IZusatzfeld> mZusatzwerte;

    @SuppressLint("Range")
    public StempeluhrStatus(Arbeitsplatz job, int position) {
        super(job, (int)job.getId(), ZUSATZ);

        // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getReadableDatabase();
        listPosition = position;

        // Einstellungen aus der Datenbank lesen
        Cursor result = ASettings.mDatenbank.rawQuery(
                SQL_READ_STATUS,
                new String[]{Long.toString(job.getId())}
        );
        if (result.moveToFirst()) {
            dbId = result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_ID));
            mSchichtdefault = mJob.getDefaultSchichten().getVonId(
                    result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_SCHICHT_DEFAULT))
            );
            mSchichtname = result.getString(result.getColumnIndex(DatenbankHelper.DB_F_NAME));
            mAbwesenheit = mJob.getAbwesenheiten().getVonId(
                    result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_ABWESENHEIT))
            );
            if (isEinsatzort()) {
                mEinsatzort = mJob.getEinsatzortListe().getOrt(
                        result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_EORT))
                );
            } else {
                mEinsatzort = null;
            }

            // Zusatzwerte aus der Datenbank lesen
            if (isZusatzwerte()) {
                // alle Zusatzwerte anlegen
                mZusatzwerte = new ArrayList<>();
                for (IZusatzfeld zf : mSchichtdefault.getZusatzfelder().getListe()) {
                    mZusatzwerte.add(zf.getKopie());
                }
                // gespeicherte Zusatzwerte auslesen und in Liste übertragen
                Cursor resultZusaetze = ASettings.mDatenbank.rawQuery(
                        SQL_READ_ZUSAETZE,
                        new String[]{Long.toString(mID)}
                );

                while (resultZusaetze.moveToNext()) {
                    long idZusatzfeld = resultZusaetze.getLong(resultZusaetze.getColumnIndex(DatenbankHelper.DB_F_ZUSATZFELD));
                    String wert = resultZusaetze.getString(resultZusaetze.getColumnIndex(DatenbankHelper.DB_F_WERT));

                    for (IZusatzfeld zf : mZusatzwerte) {
                        if(zf.getDefinitionID() == idZusatzfeld){
                            zf.setWert(wert);
                        }
                    }

                    /*IZusatzfeld newFeld;
                    ZusatzfeldDefinition def;
                    def = mJob.getZusatzDefinition(
                            resultZusaetze.getLong(resultZusaetze.getColumnIndex(Datenbank.DB_F_ZUSATZFELD)));
                    if (def != null){
                        newFeld = def.makeNewZusatzfeld(-1, resultZusaetze);
                        newFeld.setId(
                                resultZusaetze.getLong(resultZusaetze.getColumnIndex(Datenbank.DB_F_ID))
                        );
                        mZusatzwerte.add(newFeld);
                    }*/
                }
                resultZusaetze.close();
            }
        } else {
            mSchichtdefault = mJob.getDefaultSchichten().getAktive(0);
            mAbwesenheit = mJob.getAbwesenheiten().getAktive(Abwesenheit.ARBEITSZEIT);
            if (isEinsatzort()) {
                mEinsatzort = mJob.getEinsatzortListe().getOrt(mSchichtdefault.getEinsatzOrt());
            }

            // Zusatzwerte
            if (isZusatzwerte()) {
                mZusatzwerte = new ArrayList<>();
                for (IZusatzfeld zf : mSchichtdefault.getZusatzfelder().getListe()) {
                    mZusatzwerte.add(zf.getKopie());
                }
            }
        }
        result.close();

        // Widgetwerte aus den Preferencen lesen
        load(ASettings.mPreferenzen);
    }

    @Override
    public void start() {
        super.start();
        save(ASettings.mPreferenzen);
    }

    @Override
    public void startPause() {
        super.startPause();
        save(ASettings.mPreferenzen);
    }

    @Override
    public void stopPause() {
        super.stopPause();
        save(ASettings.mPreferenzen);
    }

    @Override
    public void stop() {
        super.stop();
        super.reset();
        delete(ASettings.mPreferenzen);
    }

    void setVon(int minuten) {
        super.mBeginn.set(minuten);
        save(ASettings.mPreferenzen);
    }

    void setAbwesenheit(Abwesenheit abw) {
        mAbwesenheit = abw;
        save(ASettings.mPreferenzen);
    }

    void setEinsatzort(Einsatzort eort) {
        mEinsatzort = eort;
        save(ASettings.mPreferenzen);
    }

    void setSchichtname(String name){
        mSchichtname= name;
        mSchichtdefault = null;
        save(ASettings.mPreferenzen);
    }

    void setDefaultSchicht(SchichtDefault schicht){
        if(schicht != null) {
            // Zusatzwerte übertragen wenn Sie nicht geändert wurden
            int i = 0;
            for (IZusatzfeld zf : mSchichtdefault.getZusatzfelder().getListe()) {
                IZusatzfeld wertManuell = mZusatzwerte.get(i);
                if (zf.getStringWert(false).equals(wertManuell.getStringWert(false))) {
                    wertManuell.set(zf);
                }
                i++;
            }
            if (mEinsatzort == null) {
                mEinsatzort = mJob.getEinsatzortListe().getOrt(schicht.getEinsatzOrt());
            }
        }

        mSchichtdefault = schicht;
        save(ASettings.mPreferenzen);
    }

    public void setPauseManuell(int minuten) {
        if (mStatus == WIDGET_STATUS_PAUSE) {
            mStatus = WIDGET_STATUS_RUN;
            mPauseLaenge.get(mPauseLaenge.size() - 1).set(minuten);
            super.updatePauseSumme();
        } else if (mStatus == WIDGET_STATUS_RUN) {
            super.startPause();
            setPauseManuell(minuten);
        }
        save(ASettings.mPreferenzen);
    }

    boolean isEinsatzort() {
        return mJob.isOptionSet(Arbeitsplatz.OPT_WERT_EORT);
    }

    boolean isDezimal() {
        return mJob.isOptionSet(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL);
    }

    boolean isZusatzwerte() {
        return mJob.getZusatzfeldListe().size() > 0;
    }

    long getId(){
        return mID;
    }

    int getListPosition(){
        return listPosition;
    }

    Datum getTag(){
        return mTag;
    }

    ArrayList<IZusatzfeld> getZusatzwertListe() {
        return mZusatzwerte;
    }

    SchichtDefault getDefaultSchicht(){
        return mSchichtdefault;
    }

    String getSchichtname() {
        return mSchichtname;
    }

    Uhrzeit getVon() {
        return runden(mBeginn.getAlsMinuten(), mRundenVon, mRundenVon_minuten);
    }

    Uhrzeit getBis() {
        Uhrzeit bis;
        if (mStatus == WIDGET_STATUS_NEU) {
            bis = new Uhrzeit(0);
        } else {
            bis = runden(new Uhrzeit().getAlsMinuten(), mRundenBis, mRundenBis_minuten);
        }
        return bis;
    }

    Uhrzeit getStempelzeit() {
        int zeit = getBis().getAlsMinuten() - getVon().getAlsMinuten();
        if (zeit < 0) {
            zeit += Minuten_TAG;
        }
        zeit -= getPause().getAlsMinuten();

        return new Uhrzeit(zeit);
    }

    Uhrzeit getPause() {
        return runden(mPauseSumme.getAlsMinuten(), mRundenPause, mRundenPause_minuten);
    }

    Einsatzort getEinsatzort() {
        return mEinsatzort;
    }

    String getEinsatzortName() {
        if (mEinsatzort != null) {
            return mEinsatzort.getName();
        }
        return "";
    }

    Abwesenheit getAbwesenheit() {
        if (mAbwesenheit != null) {
            return mAbwesenheit;
        }
        return mJob.getAbwesenheiten().getAktive(Abwesenheit.KEINESCHICHT);
    }

    public Arbeitsplatz getArbeitsplatz() {
        return mJob;
    }

    @NonNull
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    protected void save(SharedPreferences prefs) {
        if (mStatus != WIDGET_STATUS_NEU) {
            // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
            ContentValues werte = new ContentValues();
            werte.put(DatenbankHelper.DB_F_JOB, mJob.getId());
            if (mSchichtdefault != null) {
                werte.put(DatenbankHelper.DB_F_SCHICHT_DEFAULT, mSchichtdefault.getID());
            }
            if (mSchichtname != null) {
                werte.put(DatenbankHelper.DB_F_NAME, mSchichtname);
            }
            werte.put(DatenbankHelper.DB_F_ABWESENHEIT, mAbwesenheit.getID());
            if (isEinsatzort() && mEinsatzort != null) {
                werte.put(DatenbankHelper.DB_F_EORT, mEinsatzort.getId());
            }

            if (dbId < 0) {
                // Datensatz anlegen
                dbId = ASettings.mDatenbank.insert(DatenbankHelper.DB_T_STEMPELUHR_STATUS, null, werte);
            } else {
                // Datensatz updaten
                ASettings.mDatenbank.update(
                        DatenbankHelper.DB_T_STEMPELUHR_STATUS,
                        werte,
                        DatenbankHelper.DB_F_ID + "=?",
                        new String[]{Long.toString(dbId)}
                );
            }

            // Zusatzwerte speichern
            if (isZusatzwerte()) {
                for (IZusatzfeld zf : mZusatzwerte) {
                    werte.clear();
                    werte.put(DatenbankHelper.DB_F_STEMPELUHR_STATUS, mID);
                    werte.put(DatenbankHelper.DB_F_ZUSATZFELD, zf.getDefinitionID());
                    werte.put(DatenbankHelper.DB_F_WERT, zf.getStringforDatenbank());

                    if (zf.getId() < 0) {
                        zf.setId(ASettings.mDatenbank.insert(
                                DatenbankHelper.DB_T_STEMPELUHR_ZUSATZWERT,
                                null,
                                werte));
                    } else {
                        ASettings.mDatenbank.update(
                                DatenbankHelper.DB_T_STEMPELUHR_ZUSATZWERT,
                                werte,
                                DatenbankHelper.DB_F_ID + "=?",
                                new String[]{Long.toString(zf.getId())}
                        );
                    }
                }
            }
            super.save(prefs);
        }
    }

    public void delete(SharedPreferences prefs) {
        String id = ZUSATZ + mID;
        SharedPreferences.Editor mPrefs = prefs.edit();
        mPrefs.remove(KEY_JOB + id);
        mPrefs.remove(KEY_STATUS + id);
        mPrefs.remove(KEY_DATUM + id);
        mPrefs.remove(KEY_ZEIT + id);
        mPrefs.remove(KEY_PAUSE_BEGINN + id);
        mPrefs.remove(KEY_PAUSESUMME + id);
        mPrefs.remove(KEY_OPT_OPTIONEN + id);
        mPrefs.remove(KEY_OPT_RUNDEN + id);
        mPrefs.remove(KEY_OPT_RUNDEN_MINUTEN + id);
        mPrefs.remove(KEY_OPT_RUNDEN_VON + id);
        mPrefs.remove(KEY_OPT_RUNDEN_VON_MINUTEN + id);
        mPrefs.remove(KEY_OPT_RUNDEN_BIS + id);
        mPrefs.remove(KEY_OPT_RUNDEN_BIS_MINUTEN + id);
        mPrefs.remove(KEY_OPT_RUNDEN_PAUSE + id);
        mPrefs.remove(KEY_OPT_RUNDEN_PAUSE_MINUTEN + id);

        int i = 0;
        while (prefs.contains(i + KEY_PAUSE_BEGINN + id)) {
            mPrefs.remove(i + KEY_PAUSE_BEGINN + id);
            mPrefs.remove(i + KEY_PAUSE_LAENGE + id);
            i++;
        }

        i = 0;
        while (prefs.contains(i + KEY_TIMER_MIN + id)) {
            mPrefs.remove(i + KEY_TIMER_MIN + id);
            mPrefs.remove(i + KEY_TIMER_TEXT + id);
            mPrefs.remove(i + KEY_TIMER_SOUND + id);
            i++;
        }
        mPrefs.apply();

        //alle Stempeluhren des Arbeitsplatzes löschen
        // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
        ASettings.mDatenbank.delete(
                DatenbankHelper.DB_T_STEMPELUHR_STATUS,
                DatenbankHelper.DB_F_JOB + "=?",
                new String[]{Long.toString(mID)}
        );

        mID = (int)mJob.getId();
        mSchichtname = null;
        mSchichtdefault = super.mJob.getDefaultSchichten().getAktive(0);
        mEinsatzort = null;

        // alle Zusatzwerte löschen und neu initialisieren
        if (isZusatzwerte()) {
            ASettings.mDatenbank.delete(
                    DatenbankHelper.DB_T_STEMPELUHR_ZUSATZWERT,
                    DatenbankHelper.DB_F_STEMPELUHR_STATUS + "=?",
                    new String[]{Long.toString(mID)}
            );
            mZusatzwerte = new ArrayList<>();
            for (IZusatzfeld zf : mSchichtdefault.getZusatzfelder().getListe()) {
                mZusatzwerte.add(zf.getKopie());
            }
        }
    }

}
