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

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.text.format.DateFormat;

import java.util.ArrayList;
import java.util.Date;

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

/**
 * @author askanimus@gmail.com on 08.08.15.
 */
public class Arbeitsschicht {
    public static final int WERT_NAME_SCHICHT = 0;
    public static final int WERT_VON = 1;
    public static final int WERT_BIS = 2;
    public static final int WERT_PROZENT = 3;
    public static final int WERT_STUNDEN = 4;
    public static final int WERT_PAUSE = 5;
    public static final int WERT_EORT = 6;
    public static final int WERT_ZUSATZ_ZAHL = 11;
    public static final int WERT_ZUSATZ_ZEIT = 12;
    public static final int WERT_ZUSATZ_TEXT = 13;
    public static final int WERT_ZUSATZ_ZAHL_VON = 21;
    public static final int WERT_ZUSATZ_ZAHL_BIS = 22;
    public static final int WERT_ZUSATZ_ZEIT_VON = 23;
    public static final int WERT_ZUSATZ_ZEIT_BIS = 24;
    public static final int WERT_ZUSATZ_AUSWAHL = 25;
    public static final int WERT_ZUSATZ_PROZENT = 26;
    public static final String SQL_READ_SCHICHT =
            "select * from "
                + DatenbankHelper.DB_T_SCHICHT
                + " where "
                + DatenbankHelper.DB_F_ID
                + " = ?"
                + " limit 1";

    private final long TagId;
    private long SchichtId = -1;
    private long SchichtDefaultID = -1;
    private int Position;

    private int Von = 0;        // in Minuten
    private int Bis = 0;        // in Minuten
    private int Pause = 0;      // in Minuten
    private ZusatzWertListe mZusatzfelder;
    private String Name;

    // UNIX Timestamp der die letzte Änderung an Abwesenheit, von, bis oder Pause dokumentiert
    private Date letzteAenderung = new Date(0);
    // UNIX Timestamp der das erste Anlegen der Schicht dokumentiert
    private Date eintragAngelegt = new Date(0);

    // nicht mit gespeicherte Variablen
    //private boolean istGeandert = false;
    private final Arbeitsplatz mArbeitsplatz;
    private Abwesenheit mAbwesenheit;
    private Einsatzort mEinsatzort = null;
    private int mBrutto = 0;      // in Minuten
    //private final byte mWochentag;
    private final long mDatum;

    private int mTagSoll;
    private int mTagSollPauschal;


    /**
     * eine Schicht mit Daten aus der Datenbank anlegen
     * @param job der aktuell angezeigte Arbeitsplatz
     * @param daten die Daten aus der Datenbank
     * @param datum Datumsobjekt des betreffenden Datums
     * @param tagSoll Sollstunden des konkreten Tages (Brutto)
     * @param tagSollPauschal pauschale Sollstunden für einen Tag des betreffenden Monats
     */
    @SuppressLint("Range")
    public Arbeitsschicht(
            Arbeitsplatz job,
            //byte tag,
            Cursor daten,
            Datum datum,
            int tagSoll, int tagSollPauschal
    ) {
        //mWochentag = tag;
        mDatum = datum.getTimeInMillis();//new Datum(datum);
        mArbeitsplatz = job;
        mTagSoll = tagSoll;
        mTagSollPauschal = tagSollPauschal;

        TagId = daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_TAG));
        SchichtId = daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_ID));
        Position = daten.getInt(daten.getColumnIndex(DatenbankHelper.DB_F_NUMMER));
        SchichtDefaultID = daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_SCHICHT_DEFAULT));
            /*if (mArbeitsplatz.isTeilschicht() && SchichtDefaultID < 0 && Position < mArbeitsplatz.getAnzahlSchichtenTag())
                SchichtDefaultID = mArbeitsplatz.getDefaultSchichten().getAktive(Position).getID();*/
        Von = daten.getInt(daten.getColumnIndex(DatenbankHelper.DB_F_VON));
        Bis = daten.getInt(daten.getColumnIndex(DatenbankHelper.DB_F_BIS));
        Pause = daten.getInt(daten.getColumnIndex(DatenbankHelper.DB_F_PAUSE));
        mAbwesenheit = job.getAbwesenheiten().getVonId(daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_ABWESENHEIT)));
        long eortID = daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_EORT));
        if (eortID > 0)
            mEinsatzort = job.getEinsatzortListe().getOrt(eortID);

        mZusatzfelder = new ZusatzWertListe(SchichtId, mArbeitsplatz.getZusatzfeldListe(), false);

        Name = daten.getString(daten.getColumnIndex(DatenbankHelper.DB_F_NAME));
        if (Name == null || Name.isEmpty()) {
            if (SchichtDefaultID > 0) {
                try {
                    Name = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID).getName();
                } catch (NullPointerException ne) {
                    Name = null;
                }
                //speichern();
            } else
                Name = null;
        } else {
            /* ist notwendig weil in älteren Versionen ein kleiner Zusatz mit gespeichert wurde*/
            if (Name.startsWith(ISettings.NAME_ZUSATZ))
                Name = Name.substring(1);
        }

        letzteAenderung = new Date(daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_LETZTE_AENDERUNG)));
        eintragAngelegt = new Date(daten.getLong(daten.getColumnIndex(DatenbankHelper.DB_F_ANGELEGT)));

        berechneBrutto();
    }

    // neue Schicht mit Defaultwerten anlegen
    public Arbeitsschicht(
            int position,
            Arbeitsplatz job,
            long tagID,
            //byte tag,
            SchichtDefault dSchicht,
            Datum datum,
            int tagSoll,
            int tagSollPauschal
    ) {
        TagId = tagID;
        //mWochentag = tag;
        mDatum = datum.getTimeInMillis();//new Datum(datum);
        mArbeitsplatz = job;
        Position = position;
        mTagSoll = tagSoll;
        mTagSollPauschal = tagSollPauschal;

        if(dSchicht != null) {
            Name = dSchicht.getName();
            SchichtDefaultID = dSchicht.getID();
        }


        mZusatzfelder = new ZusatzWertListe(mArbeitsplatz.getZusatzfeldListe(), true);

        // Abwesenheit und damit Defaultwerte setzen und Schicht speichern
        setAbwesenheit(job.getAbwesenheiten().getAktive(Abwesenheit.KEINESCHICHT), 100);
    }


    // neue Schicht mit Defaultwerten anlegen
    public Arbeitsschicht(
            int position,
            Arbeitsplatz job,
            long tagID,
            //byte tag,
            String name,
            Datum datum,
            int tagSoll,
            int tagSollPauschal
    ) {
        TagId = tagID;
        //mWochentag = tag;
        mDatum = datum.getTimeInMillis();//new Datum(datum);
        mArbeitsplatz = job;
        Name = name;
        Position = position;
        mTagSoll = tagSoll;
        mTagSollPauschal = tagSollPauschal;
        mZusatzfelder = new ZusatzWertListe(mArbeitsplatz.getZusatzfeldListe(), true);

        setAbwesenheit(job.getAbwesenheiten().getAktive(Abwesenheit.KEINESCHICHT), 100);
    }

    // neue Schicht mit den Daten einer anderen Schicht erzeugen
    public Arbeitsschicht(
            long tagID,
            Arbeitsschicht quellSchicht,
            int tagSoll,
            int tagSollPauschal
    ) {
        TagId = tagID;
        //mWochentag = quellSchicht.mWochentag;
        mDatum = quellSchicht.mDatum;//new Datum(quellSchicht.mDatum);
        SchichtDefaultID = quellSchicht.SchichtDefaultID;
        Position = quellSchicht.Position;
        Von = quellSchicht.Von;
        Bis = quellSchicht.Bis;
        Pause = quellSchicht.Pause;
        Name = quellSchicht.Name;
        mAbwesenheit = quellSchicht.mAbwesenheit;
        mArbeitsplatz = quellSchicht.mArbeitsplatz;
        mBrutto = quellSchicht.mBrutto;
        mTagSoll = tagSoll;
        mTagSollPauschal = tagSollPauschal;
        if (quellSchicht.mEinsatzort != null) {
            mEinsatzort = quellSchicht.mEinsatzort;
            mEinsatzort.add_Verwendung(true, mDatum);
        }

        letzteAenderung = new Date();
        eintragAngelegt = new Date(letzteAenderung.getTime());

        mZusatzfelder = quellSchicht.mZusatzfelder.copy(getArbeitsplatz());
        berechneBrutto();
        speichern();
    }
    
    @SuppressLint("Range")
    public void reload() {
        // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getReadableDatabase();

        Cursor result = ASettings.mDatenbank.rawQuery(
                SQL_READ_SCHICHT,
                new String[]{Long.toString(SchichtId)}
                );

        if (result.getCount() > 0) {
            result.moveToFirst();

            SchichtId = result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_ID));
            SchichtDefaultID = result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_SCHICHT_DEFAULT));
            Position = result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_NUMMER));
            Name = result.getString(result.getColumnIndex(DatenbankHelper.DB_F_NAME));
            if (Name == null/* || Name.equals("")*/) {
                if( SchichtDefaultID > 0) {
                    Name = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID).getName();
                }
            }else {
                /* ist notwendig weil in älteren Versionen ein kleiner Zusatz mit gespeichert wurde*/
                if (Name.startsWith(ISettings.NAME_ZUSATZ))
                    Name = Name.substring(1);
            }

            Von = result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_VON));
            Bis = result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_BIS));
            Pause = result.getInt(result.getColumnIndex(DatenbankHelper.DB_F_PAUSE));
            mAbwesenheit = mArbeitsplatz.getAbwesenheiten().getVonId(result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_ABWESENHEIT)));
            letzteAenderung = new Date(result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_LETZTE_AENDERUNG)));
            eintragAngelegt = new Date(result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_ANGELEGT)));
            long eortID = result.getLong(result.getColumnIndex(DatenbankHelper.DB_F_EORT));
            if (eortID > 0)
                mEinsatzort = mArbeitsplatz.getEinsatzortListe().getOrt(eortID);
            else
                mEinsatzort = null;

            mZusatzfelder = new ZusatzWertListe(SchichtId, mArbeitsplatz.getZusatzfeldListe(), false);

            berechneBrutto();
        }
        result.close();
        // ASettings.ASettings.mDatenbank.close();
    }


    //
    // Daten der Schicht in datenbank schreiben
    //
    public void speichern() {

        if (mAbwesenheit.getKategorie() != Abwesenheit.KAT_KEINESCHICHT) {
            // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
            ContentValues werte = new ContentValues();
            werte.put(DatenbankHelper.DB_F_TAG, TagId);
            werte.put(DatenbankHelper.DB_F_SCHICHT_DEFAULT, SchichtDefaultID);
            werte.put(DatenbankHelper.DB_F_NUMMER, Position);
            // der Schichtname wird nur gespeichert wenn er sich vom Defaultschichtname unterscheidet oder wenn keine Defaultschicht hinterlegt wurde
            if (Name != null) {
                werte.put(DatenbankHelper.DB_F_NAME, Name);
            }

            werte.put(DatenbankHelper.DB_F_VON, Von);
            werte.put(DatenbankHelper.DB_F_BIS, Bis);
            werte.put(DatenbankHelper.DB_F_PAUSE, Pause);
            werte.put(DatenbankHelper.DB_F_ABWESENHEIT, mAbwesenheit.getID());
            werte.put(DatenbankHelper.DB_F_LETZTE_AENDERUNG, letzteAenderung.getTime());
            werte.put(DatenbankHelper.DB_F_ANGELEGT, eintragAngelegt.getTime());
            if (mEinsatzort != null)
                werte.put(DatenbankHelper.DB_F_EORT, mEinsatzort.getId());
            else
                werte.put(DatenbankHelper.DB_F_EORT, -1);

            if (SchichtId < 0) {
                SchichtId =
                        ASettings.mDatenbank.insert(DatenbankHelper.DB_T_SCHICHT, null, werte);
                mZusatzfelder.setSchichtId(SchichtId);
            } else {
                ASettings.mDatenbank.update(DatenbankHelper.DB_T_SCHICHT, werte, DatenbankHelper.DB_F_ID + "=?", new String[]{Long.toString(SchichtId)});
            }
            //// ASettings.mDatenbank.close();
            mZusatzfelder.speichern();

            // ASettings.mDatenbank.close();
        } else {
            loeschen();
            mZusatzfelder = new ZusatzWertListe(mArbeitsplatz.getZusatzfeldListe(), true);
            SchichtId = -1;
        }

    }

    //
    // Schicht aus der datenbank löschen
    //
    public void loeschen() {
        if (mEinsatzort != null) {
            mEinsatzort.sub_Verwendung();
        }
        if(SchichtId > 0) {
            // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
            ASettings.mDatenbank.delete(DatenbankHelper.DB_T_SCHICHT, DatenbankHelper.DB_F_ID + "=?", new String[]{Long.toString(SchichtId)});
            // die, mit dieser Schicht verbundenen, Zusatzwerte löschen
            ASettings.mDatenbank.delete(DatenbankHelper.DB_T_ZUSATZWERT, DatenbankHelper.DB_F_SCHICHT + "=?", new String[]{Long.toString(SchichtId)});

            // ASettings.mDatenbank.close();
        }
    }

    protected void setName(String name){
        if(Name == null || !Name.equals(name)) {
            Name = name;
            speichern();
        }
    }

    public void setVon(int von) {
        if (von != Von) {
            while(von >= ISettings.Minuten_TAG) {
                von -= ISettings.Minuten_TAG;
            }
            Von = von;
            letzteAenderung = new Date();
            berechneBrutto();
            speichern();
        }
    }

    public void setBis(int bis) {
        if (bis != Bis) {
            while(bis >= ISettings.Minuten_TAG) {
                bis -= ISettings.Minuten_TAG;
            }
            Bis = bis;
            letzteAenderung = new Date();
            berechneBrutto();
            speichern();
        }
    }

    /**
     * Eintragen aller Werte in eine vorhanden Schicht
     * Wenn "Arbeitszeit" als Abwesenheit gewählt wurde, werden auch die Extradaten aus einer
     * evtl. übergebenen Schichdefinition übernommen
     *
     * @param abw die Abwesenheit, die eingetragen werden soll
     * @param von Startzeit in Minuten
     * @param bis Endzeit in Minuten
     * @param pause Pausenzeit in Minuten
     * @param defSchicht die definierte Schicht als Datenbasis oder null für eine Extraschicht
     * @param name Schicntname oder null um den Namen beizubehalten
     */
    public void setAll(
            Abwesenheit abw,
            int von, int bis, int pause,
            SchichtDefault defSchicht,
            String name
    ) {
        mAbwesenheit = abw;
        while (von >= ISettings.Minuten_TAG) {
            von -= ISettings.Minuten_TAG;
        }
        Von = von;
        while (bis >= ISettings.Minuten_TAG) {
            bis -= ISettings.Minuten_TAG;
        }
        Bis = bis;
        while (pause >= ISettings.Minuten_TAG) {
            pause -= ISettings.Minuten_TAG;
        }
        Pause = pause;
        letzteAenderung = new Date();
        eintragAngelegt = new Date(letzteAenderung.getTime());

        if (name != null) {
            Name = name;
        }

        if(defSchicht != null) {
            SchichtDefaultID = mArbeitsplatz.isTeilschicht()? defSchicht.getID() : 0;
            if(mAbwesenheit.getKategorie() == Abwesenheit.ARBEITSZEIT){
                 setEinsatzort(
                       mArbeitsplatz.getEinsatzortListe().getOrt(defSchicht.getEinsatzOrt())
               );
                // wurde während des Laufs der Stempeluhr ein Zusatzwert in der App für diesen Tag geändert
                // und ist die Schichterkennung aktiv, wird der eingetragene Wert nicht durch den in de Schichtdefinition ersetzt
                int feldDefaultIndex = 0;
                for (IZusatzfeld feld : mZusatzfelder.getListe()) {
                    if(feld.istLeer()){
                        feld.set(defSchicht.getZusatzwert(feldDefaultIndex));
                    }
                    feldDefaultIndex++;
                }
                 //mZusatzfelder.setListenWerte(defSchicht.getZusatzfelder());
            }
        } else {
            SchichtDefaultID = 0;
        }

        /*if(mAbwesenheit.getKategorie() == Abwesenheit.ARBEITSZEIT && SchichtDefaultID > 0){
           SchichtDefault schichtDefault
                   = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID);
           if(schichtDefault != null) {
               setEinsatzort(
                       mArbeitsplatz.getEinsatzortListe().getOrt(defSchicht.getEinsatzOrt())
               );
               mZusatzfelder.setListenWerte(defSchicht.getZusatzfelder());
           }
        }*/

        berechneBrutto();
        speichern();
    }

    public void setTagSoll(int tagSoll, int tagSollPauschal) {
        if (mTagSoll != tagSoll || mTagSollPauschal != tagSollPauschal) {
            mTagSoll = tagSoll;
            mTagSollPauschal = tagSollPauschal;
            berechneBrutto();
            speichern();
        }
    }

    // Berechnet die Bruttoarbeitszeit
    private void berechneBrutto() {
        mBrutto = 0;

        if (mAbwesenheit != null)
            if (Von > 0 || Bis > 0) {
                switch (mAbwesenheit.getWirkung()) {
                    case Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV:
                        //if (Von > 0 || Bis > 0) {
                        if (mAbwesenheit.getKategorie() != Abwesenheit.KAT_ZUSCHLAG) {
                            mBrutto = (Bis - Von);
                            if (mBrutto <= 0)
                                mBrutto += ISettings.Minuten_TAG;
                        } else {
                            mBrutto = Bis;
                        }
                        //}
                        break;
                    case Abwesenheit.WIRKUNG_IST_PLUS_PAUSCHAL:
                        if (Bis > 0) {
                            if (mAbwesenheit.getKategorie() == Abwesenheit.KAT_ZUSCHLAG) {
                                mBrutto = Math.round(((float) mTagSollPauschal * Bis) / 100);
                            } else {
                                mBrutto = Math.round(((float) mTagSoll * Bis) / 100);
                            }
                        }
                        break;
                }
            }
    }

    public void setPause(int pause) {
        if (pause != Pause) {
            Pause = pause;
            letzteAenderung = new Date();
            speichern();
        }
    }

    public void setAbwesenheit(Abwesenheit abw, int prozent) {
        Abwesenheit abwesenheitAlt;
        SchichtDefault defSchicht = null;

        if (SchichtDefaultID > 0) {
            defSchicht = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID);
        }

        // Wenn keine Abwesenheit gesetzt ist, dann Abwesenheit.KEINESCHICHT setzen
        if (mAbwesenheit == null) {
            mAbwesenheit = mArbeitsplatz.getAbwesenheiten().get(Abwesenheit.KEINESCHICHT);
            Von = 0;
            Bis = prozent;
            Pause = 0;
            setEinsatzort(null);
            mBrutto = 0;
            if(mArbeitsplatz.isTeilschicht() && defSchicht != null){
               Name = defSchicht.getName();
            }
            // wenn auch die zu setzende Abwesenheit "Keine Schicht" ist, dann ist hier Schluss
            if(abw.getID() == mAbwesenheit.getID()) {
                speichern();
                return;            }
        }

        // sind die vorhandene und die zu setzende Abwesenheit ungleich, dann die Abwesenheit umschreiben
        if (abw.getID() != mAbwesenheit.getID()) {
            abwesenheitAlt = mAbwesenheit;
            mAbwesenheit = abw;

            if (mAbwesenheit.getKategorie() != Abwesenheit.KAT_KEINESCHICHT) {
                if (defSchicht != null) {
                    //SchichtDefault defSchicht = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID);

                    switch (mAbwesenheit.getWirkung()) {
                        case Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV:
                        case Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV:
                            if (mAbwesenheit.getKategorie() == Abwesenheit.KAT_ARBEITSZEIT) {
                                if (abwesenheitAlt.getWirkung() != Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV
                                        && abwesenheitAlt.getWirkung() != Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV
                                ) {
                                    Pause = defSchicht.getPause();
                                }
                            } else {
                                Pause = 0;
                            }

                            if (mAbwesenheit.getKategorie() != Abwesenheit.KAT_ZUSCHLAG) {
                                if (abwesenheitAlt.getWirkung() != mAbwesenheit.getWirkung()
                                        || abwesenheitAlt.getKategorie() == Abwesenheit.KAT_ZUSCHLAG
                                ) {
                                    Von = defSchicht.getVon();
                                    Bis = defSchicht.getBis();
                                    Einsatzort eort = mArbeitsplatz.getEinsatzortListe().getOrt(defSchicht.getEinsatzOrt());
                                    setEinsatzort(eort);
                                    mZusatzfelder.setListenWerte(defSchicht.getZusatzfelder());
                                }
                            } else {
                                Von = 0;
                                Bis = Math.max(0, (defSchicht.getBis() - defSchicht.getVon()));
                                setEinsatzort(null);
                            }
                            berechneBrutto();
                            break;
                        case Abwesenheit.WIRKUNG_IST_PLUS_PAUSCHAL:
                        case Abwesenheit.WIRKUNG_SOLL_MINUS_TAGE:
                        case Abwesenheit.WIRKUNG_SOLL_MINUS_STUNDEN:
                            if (abwesenheitAlt.getWirkung() != mAbwesenheit.getWirkung()) {
                                Von = 0;
                                Pause = 0;
                                //setEinsatzort(null);
                                Bis = prozent;
                                berechneBrutto();
                            }
                            //speichern();
                            break;
                        default:
                            Von = 0;
                            Bis = prozent;
                            Pause = 0;
                            setEinsatzort(null);
                            mBrutto = 0;
                    }
                } else {
                    if (abwesenheitAlt.getWirkung() != mAbwesenheit.getWirkung()) {
                        if (mAbwesenheit.getWirkung() == Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV
                                || mAbwesenheit.getWirkung() == Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV) {
                            Uhrzeit mZeit = new Uhrzeit();
                            Von = mZeit.getAlsMinuten();
                            mZeit.add(120);
                            Bis = mZeit.getAlsMinuten();
                        } else {
                            Von = 0;
                            Bis = prozent;
                        }
                        Pause = 0;
                        berechneBrutto();
                        setEinsatzort(null);
                    }
                }
            } else {
                mAbwesenheit = mArbeitsplatz.getAbwesenheiten().get(Abwesenheit.KEINESCHICHT);
                Von = 0;
                Bis = prozent;
                Pause = 0;
                setEinsatzort(null);
                mBrutto = 0;
                if(!mArbeitsplatz.isTeilschicht()) {
                    SchichtDefaultID = -1;
                    //Name = null;
                }
            }

            letzteAenderung = new Date();
            if (eintragAngelegt.getTime() == 0) {
                eintragAngelegt = new Date(letzteAenderung.getTime());
            }
            speichern();
        }
    }


    public boolean setEinsatzort(Einsatzort einsatzort) {
        boolean isGeaendert = false;
        if(einsatzort != null) {
            if(mEinsatzort == null){
                mEinsatzort = einsatzort;
                mEinsatzort.add_Verwendung(true, mDatum);
                // speichern();
                //mArbeitsplatz.getEinsatzortListe().sortNachBenutzung();
                isGeaendert = true;
            }else if (einsatzort.getId() != mEinsatzort.getId()) {
                mEinsatzort.sub_Verwendung();
                mEinsatzort = einsatzort;
                mEinsatzort.add_Verwendung(true, mDatum);
                //speichern();
                //mArbeitsplatz.getEinsatzortListe().sortNachBenutzung();
                isGeaendert = true;
            }
        } else {
            if ( mEinsatzort != null){
                mEinsatzort.sub_Verwendung();
                mEinsatzort = null;
                //speichern();
                //mArbeitsplatz.getEinsatzortListe().sortNachBenutzung();
                isGeaendert = true;
            }
        }

        if(isGeaendert) {
            mArbeitsplatz.getEinsatzortListe().sortNachBenutzung();
            speichern();
        }

        return isGeaendert;
    }


    /*public void setDefaultSchichtId(long id){
        if(id != SchichtDefaultID){
            SchichtDefaultID = id;
            speichern();
        }
    }*/

    public boolean setDefaultSchicht(SchichtDefault defSchicht) {
        if (defSchicht == null) {
            SchichtDefaultID = 0;
            speichern();
        } else if (SchichtDefaultID < 0 || SchichtDefaultID != defSchicht.getID()) {
            SchichtDefaultID = defSchicht.getID();
            Name = defSchicht.getName();
            Von = defSchicht.getVon();
            Bis = defSchicht.getBis();
            Pause = defSchicht.getPause();
            mZusatzfelder.setListenWerte(defSchicht.getZusatzfelder());

            Einsatzort eort = mArbeitsplatz.getEinsatzortListe().getOrt(defSchicht.getEinsatzOrt());
            if (!setEinsatzort(eort)) {
                speichern();
            }
            return true;
        }
        return false;
    }

    public void setPositionInListe(int position){
        if(Position != position) {
            Position = position;
            speichern();
        }
    }

    //
    // Ausgaben und Berechnungen
    //
    public long getID(){
        return SchichtId;
    }

    public long getDefaultSchichtId(){
        return SchichtDefaultID;
    }

    public int getNummer(){
        return Position;
    }

    public int getVon() {
        return Von;
    }

    public int getBis() {
        return Bis;
    }

    public int getPause() {
        return Pause;
    }

    public Abwesenheit getAbwesenheit() {
        return mAbwesenheit;
    }

    public int getWirkung() {
        return mAbwesenheit.getWirkung();
    }

    public String getName() {
        if(Name != null) {
            return Name;
        } else {
            if (SchichtDefaultID > 0){
                SchichtDefault sd = mArbeitsplatz.getDefaultSchichten().getVonId(SchichtDefaultID);
                if(sd != null) {
                    return sd.getName();
                } else {
                    return "";
                }
            }
        }
        return "";
    }

    /*protected Einsatzort getEinsatzort(){
        return mEinsatzort;
    }*/

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

    public long getIdEinsatzort(){
        if (mEinsatzort != null) {
            return mEinsatzort.getId();
        }
        return 0;
    }

    /*public Date getLetzteAenderung(){
        return letzteAenderung;
    }*/

    /*public Date getEintragAngelegt(){
        return eintragAngelegt;
    }*/

    public String getLetzteAenderungAlsString(Context context){
        if(letzteAenderung.getTime() == 0){
            return "";
        } else {
            java.text.DateFormat dFormat = DateFormat.getDateFormat(context);
            java.text.DateFormat zFormat = DateFormat.getTimeFormat(context);

            return String.format(
                    "%s %s",
                    dFormat.format(letzteAenderung),
                    zFormat.format(letzteAenderung));
        }
    }

    public String getEintragAngelegtAlsString(Context context){
        if(eintragAngelegt.getTime() == 0){
            return "";
        } else {
            java.text.DateFormat dFormat = DateFormat.getDateFormat(context);
            java.text.DateFormat zFormat = DateFormat.getTimeFormat(context);

            return String.format(
                    "%s %s",
                    dFormat.format(eintragAngelegt),
                    zFormat.format(eintragAngelegt));
        }
    }

    public boolean isZusatzwerte() {
        return mZusatzfelder.size() > 0;
    }

    public IZusatzfeld getZusatzwert(int index){
        if(index < mZusatzfelder.size())
            return mZusatzfelder.get(index);
        else
            return null;
    }

    public ZusatzWertListe getZusatzfelder(int textOption){
        if(textOption == IZusatzfeld.TEXT_VOLL){
           return mZusatzfelder;
        } else {
            ArrayList<IZusatzfeld> werte = new ArrayList<>();
            for (IZusatzfeld zf : mZusatzfelder.getListe()) {
                if (
                        textOption > IZusatzfeld.TEXT_NO ||
                        (
                                zf.getDatenTyp() != IZusatzfeld.TYP_TEXT && zf.getDatenTyp() != IZusatzfeld.TYP_AUSWAHL_TEXT
                        )
                ) {
                    if(
                            (
                                    zf.getDatenTyp() == IZusatzfeld.TYP_TEXT || zf.getDatenTyp() == IZusatzfeld.TYP_AUSWAHL_TEXT
                            )
                                    && textOption == IZusatzfeld.TEXT_LEER
                    ) {
                        werte.add( zf.getDefinition().makeNewZusatzfeld());
                    } else {
                        werte.add(zf);
                    }
                }
            }
            return new ZusatzWertListe(werte);
        }
    }

    public int getBrutto(){
        return mBrutto;
    }

    public Arbeitsplatz getArbeitsplatz(){
        return mArbeitsplatz;
    }

    /*public int getWochentag(){
        return mDatum.get(Calendar.DAY_OF_WEEK);
    }*/


    public float getMinusSollTage(){
        float wert = 0;
        if(mAbwesenheit != null) {
            if (mAbwesenheit.getWirkung() == Abwesenheit.WIRKUNG_SOLL_MINUS_TAGE) {
                if (Bis > 0 && mTagSoll > 0)
                    wert = ((float) Bis / 100);
            }
        }
        return wert;
    }

    public int getMinusSollMinuten(){
        int wert = 0;

        if(mAbwesenheit != null) {
            switch (mAbwesenheit.getWirkung()) {
                case Abwesenheit.WIRKUNG_SOLL_MINUS_STUNDEN:
                    if (Bis > 0)
                        wert = Math.round(Bis * mTagSoll / 100f);
                    break;
                case Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV:
                    wert = (Bis - Von);
                    if (wert <= 0)
                        wert += ISettings.Minuten_TAG;
                    break;
            }
        }
        return wert + mZusatzfelder.getSummeMinusSollZeit(mTagSoll);
    }

    // Nur bei Arbeitszeit wird der Bruttowert korrigiert ansonsten durchgereicht
    public int getNetto() {
        int wert = mBrutto;

        // die unbezahlte Pause von der Arbeitszeit abziehen
        if (mAbwesenheit.getKategorie() == Abwesenheit.KAT_ARBEITSZEIT) {
            if (!mArbeitsplatz.isOptionSet(Arbeitsplatz.OPT_PAUSE_BEZAHLT)) {
                wert -= Pause;
            }
        }

        wert += mZusatzfelder.getSummeKorrekturIstZeit(wert);

        return Math.max(wert, 0);
    }

    /**
     * Berechnet die Anzahl Minuten die für den Verdienst relevant sind für diese Schicht
     * @return Anzahl der Minuten für Verdienst
     */
    public float getVerdienstMinuten(){
        float mWert = 0;

        if(mAbwesenheit.getKategorie() != Abwesenheit.KAT_UNBEZAHLT) {
            switch (mAbwesenheit.getWirkung()) {
                case Abwesenheit.WIRKUNG_SOLL_MINUS_EFFEKTIV:
                case Abwesenheit.WIRKUNG_SOLL_MINUS_STUNDEN:
                    mWert = getMinusSollMinuten();
                    break;
                case Abwesenheit.WIRKUNG_SOLL_MINUS_TAGE:
                    mWert = getMinusSollTage() * mTagSoll;
                    break;
                case Abwesenheit.WIRKUNG_IST_PLUS_PAUSCHAL:
                case Abwesenheit.WIRKUNG_IST_PLUS_EFFEKTIV:
                    mWert = getNetto();
                    break;
            }
            //mWert /= 60;
            //mWert = Math.round(mWert * 100.0f) / 100.0f;
            //mWert = mWert * mArbeitsplatz.getStundenlohn();
        }

        //mWert += mZusatzfelder.getSummeKorrekturVerdienst();

        return mWert;
    }

    //Summe der, den Verdienst korrigierenden Werte
    public float getKorrekturVerdienst(float verdienstMinuten){
        return mZusatzfelder.getSummeKorrekturVerdienst(verdienstMinuten, mArbeitsplatz.getStundenlohn());
    }

    // Nettostunden ausgeben wenn der Einsatzort stimmt
    public int getEortNetto(long eortID){
        long id = mEinsatzort == null ? 0 : mEinsatzort.getId();
        if(id == eortID){
            return getNetto();
        } else {
            return 0;
        }
    }
}
