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

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;

import askanimus.arbeitszeiterfassung2.MainActivity;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.setup.ASettings;
import askanimus.arbeitszeiterfassung2.setup.ISettings;
import askanimus.arbeitszeiterfassung2.setup.SettingsActivity;
import askanimus.arbeitszeiterfassung2.stempeluhr.StempeluhrListe;
import askanimus.arbeitszeiterfassung2.stempeluhr.StempeluhrStatus;
import askanimus.arbeitszeiterfassung2.widget.Widget;
import askanimus.arbeitszeiterfassung2.widget.WidgetStatus;

public class NfcHelperActivity extends Activity implements ISettings  {
    private final int NFC_AKTION_KEINE = 0;
    private final int NFC_AKTION_START = 1;
    private final int NFC_AKTION_PAUSE = 2;
    private final int NFC_AKTION_STOP = 3;

    private NfcAdapter nfcAdapter = null;
    //private NfcTagListe nfcTagListe = null;

    Context mContext;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        mContext = getApplicationContext();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (nfcAdapter != null) {
            // Einstellungen laden, wenn noch nicht geschehen
            ASettings.init(this, this::resume);
        }
        finish();
    }

    private void resume() {
        // if (nfcAdapter != null) {
        Intent intent = getIntent();
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
            // die Tag ID lesen und in eine vorzeichenlose Zahl umwandeln
            long tagID = getNfcTagId(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));

            if (ASettings.mPreferenzen.getBoolean(KEY_NFC_EDIT, false)) {
                // wenn dieser Tag schon für einen anderen Arbeitsplatz registriert wurde,
                // eine Fehlermeldung ausgeben
                NfcTagListe nfcTagListe = new NfcTagListe();
                int tagIndex = nfcTagListe.getTagIndex(tagID);
                if (tagIndex >= 0) {
                    NfcBekannterTag tag = nfcTagListe.get(tagIndex);
                    if (tag.getArbeitsplatzID() != ASettings.mPreferenzen.getLong(ISettings.KEY_EDIT_JOB, 0)) {
                        tagID = 0;
                        Toast.makeText(mContext, "Dieser NFC Tag ist schon für den Arbeitsplatz '"
                                + ASettings.getArbeitsplatz(tag.getArbeitsplatzID()).getName()
                                + "' registriert.", Toast.LENGTH_LONG).show();
                    }
                }
                // wenn die Einstellungen offen sind, zu diesen springen
                Intent mSettingsIntent = new Intent();
                mSettingsIntent.setClass(this, SettingsActivity.class);
                mSettingsIntent.putExtra(ISettings.KEY_EDIT_JOB, ASettings.mPreferenzen.getLong(ISettings.KEY_EDIT_JOB, 0));
                mSettingsIntent.putExtra(ISettings.KEY_INIT_SEITE, ISettings.SETUP_SEITE_NFC);
                mSettingsIntent.putExtra(ISettings.KEY_NFC_TAG, tagID);
                mSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mSettingsIntent);
            } else {
                // auf den Tag reagieren wenn er registriert ist und eine Aktion hinterlegt wurde

                // Die Liste aller bekannten Tags anlegen
                NfcTagListe nfcTagListe = new NfcTagListe();

                // Den Tag in der Liste finden
                int tagIndex = nfcTagListe.getTagIndex(tagID);
                if (tagIndex >= 0) {
                    // Der Tag existiert in der Liste
                    NfcBekannterTag mTag = nfcTagListe.get(tagIndex);

                    // ist NFC für den betreffenden Arbeitsplatz aktiv?
                    Arbeitsplatz job = ASettings.getArbeitsplatz(mTag.getArbeitsplatzID());
                    if (job != null && job.isNfcAktiv()) {
                        String meldung;
                        // wenn ja, dann das betreffende Widget finden und die Aktion auslösen

                        // Die aktuellen Widgets durchsuchen, ob eines des Arbeitsplatzes des Tags läuft
                        AppWidgetManager wm = AppWidgetManager.getInstance(mContext);
                        ComponentName cn = new ComponentName(mContext.getPackageName(), Widget.class.getName());
                        int[] widgetIds = wm.getAppWidgetIds(cn);
                        int widgetAtion = widgetAktion(mTag, widgetIds);
                        if (widgetAtion == NFC_AKTION_KEINE) {
                            widgetAtion = stempeluhrAktion(mTag, widgetIds);
                        }
                        if (widgetAtion > NFC_AKTION_KEINE) {
                            // es wurde ein Widget gefunden und gesteuert
                            switch (widgetAtion) {
                                case NFC_AKTION_START:
                                    meldung = String.format(getString(R.string.nfc_start), job.getName());
                                    break;
                                case NFC_AKTION_PAUSE:
                                    meldung = String.format(getString(R.string.nfc_pause), job.getName());
                                    break;
                                default:
                                    meldung = String.format(getString(R.string.nfc_stop), job.getName());
                                    break;
                            }
                        } else {
                            meldung = String.format(
                                    getString(R.string.nfc_no_action),
                                    (mTag.getAktion() == INfc.TAG_AKTION_START_STOP) ?
                                            getString(R.string.nfc_aktion_start_stop) : getString(R.string.pause),
                                    job.getName()
                            );
                        }
                        Toast.makeText(
                                this,
                                meldung,
                                Toast.LENGTH_LONG
                        ).show();
                    }
                }
            }
        } else {
            // zu den Einstellungen zurückkeheren
            Intent mSettingsIntent = new Intent();
            mSettingsIntent.setClass(this, SettingsActivity.class);
            mSettingsIntent.putExtra(ISettings.KEY_EDIT_JOB, ASettings.mPreferenzen.getLong(ISettings.KEY_EDIT_JOB, 0));
            mSettingsIntent.putExtra(ISettings.KEY_INIT_SEITE, ISettings.SETUP_SEITE_NFC);
            mSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(mSettingsIntent);
            if (ACTION_NFC_AKTIVIEREN.equals(action)) {
                // wenn NFC ausgeschaltet ist, dieses einschalten lassen
                if (!nfcAdapter.isEnabled()) {
                    openNfcSettings();
                }
            } else if (ACTION_NFC_DEAKTIVIEREN.equals(action)) {
                // wenn NFC eingeschaltet ist, dieses ausschalten lassen
                if (nfcAdapter.isEnabled()) {
                    openNfcSettings();
                }
            }
        }
        // }
    }


    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    /**
     * NFC vom User einschalten lassen
     */
    private void openNfcSettings() {
        Intent intent;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            intent = new Intent(Settings.Panel.ACTION_NFC);
        } else {
            intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
        }
        startActivity(intent);
    }

    /**
     * Gibt die UID des erkannten Tags zurück
     *
     * @param tag die Daten des gelesenen Tags
     */
    private long getNfcTagId(Tag tag) {
        long tagIDNumber = 0;
        // aus dem Byte Array der ID die Dezimalzahl bilden
        if (tag != null) {
            byte[] tagID = tag.getId();
            long faktor = 1;
            for (byte b : tagID) {
                tagIDNumber += Byte.toUnsignedInt(b) * faktor;
                faktor *= 256L;
            }
        }
        return tagIDNumber;
    }

    private int widgetAktion(NfcBekannterTag nfcTag, int[] widgetIds) {
        int nfcAktion = NFC_AKTION_KEINE;

        for (int widgetID : widgetIds) {
            Arbeitsplatz mArbeitsplatz = ASettings.getArbeitsplatz(nfcTag.getArbeitsplatzID());
            WidgetStatus status = new WidgetStatus(mArbeitsplatz, widgetID, "");
            status.load(ASettings.mPreferenzen);
            if (ASettings.mPreferenzen.getLong(WidgetStatus.KEY_JOB + widgetID, 0) == nfcTag.getArbeitsplatzID()) {
                String widgetAktion = "";

                if (nfcTag.getAktion() == INfc.TAG_AKTION_START_STOP) {
                    if (status.getStatus() == WidgetStatus.WIDGET_STATUS_NEU) {
                        widgetAktion = Widget.START_CLICKED;
                        nfcAktion= NFC_AKTION_START;
                    } else if (status.getStatus() == WidgetStatus.WIDGET_STATUS_RUN || status.getStatus() == WidgetStatus.WIDGET_STATUS_PAUSE) {
                        widgetAktion = Widget.STOP_CLICKED;
                        nfcAktion= NFC_AKTION_STOP;
                    }
                } else if (nfcTag.getAktion() == INfc.TAG_AKTION_PAUSE) {
                    if (status.getStatus() == WidgetStatus.WIDGET_STATUS_RUN) {
                        widgetAktion = Widget.PAUSE_CLICKED;
                        nfcAktion= NFC_AKTION_PAUSE;
                    } else if (status.getStatus() == WidgetStatus.WIDGET_STATUS_PAUSE) {
                        widgetAktion = Widget.START_CLICKED;
                        nfcAktion= NFC_AKTION_START;
                    }
                }

                // die gewünschte Aktion an das erste Widget senden
                if (!widgetAktion.isEmpty()) {
                    Intent widgetIntent = new Intent();
                    widgetIntent.setClass(getApplicationContext(), Widget.class);
                    widgetIntent.setAction(widgetAktion);
                    widgetIntent.putExtra(Widget.KEY_WIDGET_ID, widgetID);
                    sendBroadcast(widgetIntent);
                }
                break;
           }
        }
        return nfcAktion;
    }

    private int stempeluhrAktion(NfcBekannterTag nfcTag, int[] widgetIds){
        int nfcAktion = NFC_AKTION_KEINE;

        StempeluhrListe mStempeluhren = new StempeluhrListe(widgetIds);
        for (StempeluhrStatus stempeluhr : mStempeluhren) {
            if (stempeluhr.getArbeitsplatz().getId() == nfcTag.getArbeitsplatzID()) {
                String stempeluhrAktion = "";

                switch (stempeluhr.getStatus()) {
                    case WidgetStatus.WIDGET_STATUS_NEU:
                        if (nfcTag.getAktion() == INfc.TAG_AKTION_START_STOP) {
                            nfcAktion = NFC_AKTION_START;
                            stempeluhrAktion = StempeluhrStatus.START_PAUSE_CLICKED;
                        }
                        break;
                    case WidgetStatus.WIDGET_STATUS_RUN:
                        if (nfcTag.getAktion() == INfc.TAG_AKTION_START_STOP) {
                            nfcAktion = NFC_AKTION_STOP;
                            stempeluhrAktion = StempeluhrStatus.STOP_CLICKED;
                        } else if (nfcTag.getAktion() == INfc.TAG_AKTION_PAUSE) {
                            nfcAktion = NFC_AKTION_PAUSE;
                            stempeluhrAktion = StempeluhrStatus.START_PAUSE_CLICKED;
                        }
                        break;
                    case WidgetStatus.WIDGET_STATUS_PAUSE:
                        if (nfcTag.getAktion() == INfc.TAG_AKTION_START_STOP) {
                            nfcAktion = NFC_AKTION_STOP;
                            stempeluhrAktion = StempeluhrStatus.STOP_CLICKED;
                        } else if (nfcTag.getAktion() == INfc.TAG_AKTION_PAUSE) {
                            nfcAktion = NFC_AKTION_START;
                            stempeluhrAktion = StempeluhrStatus.START_PAUSE_CLICKED;
                        }
                        break;
                }
                // die gewünschte Aktion an die Stempeluhr senden
                if (!stempeluhrAktion.isEmpty()) {
                    Intent stempeluhrIntent = new Intent();
                    stempeluhrIntent.setClass(getApplicationContext(), MainActivity.class);
                    stempeluhrIntent.setAction(stempeluhrAktion);
                    stempeluhrIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    stempeluhrIntent.putExtra(StempeluhrStatus.KEY_STEMPELUHR_ID, nfcTag.getArbeitsplatzID());
                    stempeluhrIntent.putExtra(ISettings.KEY_ANZEIGE_VIEW, ISettings.VIEW_STEMPELUHR);
                    startActivity(stempeluhrIntent);
                }
                break;
            }

        }

        return nfcAktion;
    }

}
