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

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;

import askanimus.arbeitszeiterfassung2.MainActivity;
import askanimus.arbeitszeiterfassung2.R;
import askanimus.arbeitszeiterfassung2.StorageHelper;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.Arbeitsplatz;
import askanimus.arbeitszeiterfassung2.arbeitsplatz.ArbeitsplatzListe;
import askanimus.arbeitszeiterfassung2.datenbank.DatenbankHelper;
import askanimus.arbeitszeiterfassung2.datenbank.Datenbank_Migrate;
import askanimus.arbeitszeiterfassung2.datenbank.Datenbank_toMigrate;
import askanimus.arbeitszeiterfassung2.datensicherung.Datenbank_Backup;
import askanimus.arbeitszeiterfassung2.datensicherung.Datensicherung_ViewAdapter;

/**
 * A placeholder fragment containing a simple view.
 */
public class SettingsFragmentMigration
        extends
        Fragment
        implements
        ISettings,
        Datensicherung_ViewAdapter.ItemClickListener {

    //private final static String ARG_PFAD = "imp_pfad";

    private StorageHelper mStorageHelper = null;

    private ArrayList<String> listeSicherungen;

    private Context mContext;

    //Der Rückrufpunkt
    //migrationDone mCallback;

    /*
     * Neue Instanz anlegen
     */
    public static SettingsFragmentMigration newInstance() {
        return new SettingsFragmentMigration();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        mStorageHelper = new StorageHelper(requireActivity());
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mContext = getContext();
        return inflater.inflate(R.layout.fragment_init_migration, container, false);
    }


    @Override
    public void onResume() {
        super.onResume();
        ASettings.init(mContext, this::resume);
    }

    private void resume() {
        View v = getView();

        if (v != null) {
            RecyclerView listView = v.findViewById(R.id.DU_liste_sicherungen);

            Button buttonSuche = v.findViewById(R.id.DU_button_suche);
            ViewCompat.setBackgroundTintList(buttonSuche, ASettings.aktJob.getFarbe_Button());
            buttonSuche.setTextColor(ASettings.aktJob.getFarbe_Schrift_Button());
            buttonSuche.setOnClickListener(v1 -> mStorageHelper.waehlePfad());

            if (mStorageHelper.getPfad() == null) {
                String mPfad = Environment.getExternalStorageDirectory().toString();
                mPfad += File.separator + ASettings.res.getString(R.string.app_verzeichnis_toMigrate);
                mPfad += File.separator + getString(R.string.app_verzeichnis_backup);

                mPfad = ASettings.mPreferenzen.getString(
                        ISettings.KEY_IMPORT_DIR,
                        mPfad
                );
                mStorageHelper.setUp(
                        mPfad,
                        null,
                        null,
                        false,
                        REQ_FOLDER_PICKER_READ
                );
            }

            if (mStorageHelper.isReadable()) {
                // Die Liste der Datensicherungen erzeugen, wenn sie nicht schon angelegt wurde
                if (listeSicherungen == null) {
                    //listeSicherungen = new ArrayList<>();
                    Datensicherung_ViewAdapter myAdapter = new Datensicherung_ViewAdapter();
                    //myAdapter.setUp(listeSicherungen, this);
                    listeSicherungen = myAdapter.setUp(mContext, mStorageHelper, this, false);
                    GridLayoutManager gLayoutManager = new GridLayoutManager(
                            mContext,
                            1);
                    listView.setLayoutManager(gLayoutManager);
                    listView.setAdapter(myAdapter);
                }
            }

            /* AppCompatButton bWiederherstellen = v.findViewById(R.id.DU_button_restore);
            ViewCompat.setBackgroundTintList(bWiederherstellen, ASettings.aktJob.getFarbe_Button());
            bWiederherstellen.setTextColor(ASettings.aktJob.getFarbe_Schrift_Button());*/
        }
    }

    @Override
    public void onSicherungClick(int position, int action, View view) {
        String fileName = listeSicherungen.get(position);
        AlertDialog.Builder restorDialog = new AlertDialog.Builder(mContext);
        restorDialog.setMessage(getString(R.string.sich_frage_restore, fileName))
                .setIcon(R.mipmap.ic_launcher_foreground)
                .setTitle(R.string.sich_restore)
                .setPositiveButton(R.string.ja, (dialog, id) -> {
                    // Daten wiederherstellen
                    if (fileName.endsWith(".xml")) {
                        restoreTask(fileName, false);
                    } else if (fileName.endsWith(".db")) {
                        restoreTask(fileName, true);
                    } else {
                        importTask(fileName);
                    }

                })
                .setNegativeButton(R.string.nein, (dialog, id) -> {
                    // nichts tun
                });
        // den Dialog erzeugen und anzeigen
        restorDialog.create().show();

    }

    /*
     * Wiederherstellung der Sicherungen im Hintergrund
     */
    private void restoreTask(String pfad, boolean isDB) {
        final ProgressDialog mDialog = new ProgressDialog(mContext);

        // Fortschritsdialog öffnen
        mDialog.setIndeterminate(true);
        mDialog.setIndeterminateDrawable(
                ResourcesCompat.getDrawable(
                        getResources(),
                        R.drawable.progress_dialog_anim,
                        mContext.getTheme()));
        mDialog.setMessage(getString(R.string.progress_restore));
        mDialog.setCancelable(false);
        mDialog.show();

        Handler mHandler = new Handler();
        new Thread(() -> {
            boolean mStatus = false;
            long aktJob = 0;
            //SQLiteDatabase mDatenbank = ASettings.openDatenbank();
            Datenbank_Backup mBackup = new Datenbank_Backup(mContext, mStorageHelper);
            try {
                if (isDB){
                    aktJob = mBackup.restore(pfad);
                } else {
                    aktJob = mBackup.restoreXML(pfad);
                }
                mStatus = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            // Erfolgsmeldung ausgeben
            final boolean fStatus = mStatus;
            final long newAktJob = aktJob;
            mHandler.post(() -> {
                // Fortschrittsdialog schliessen
                mDialog.dismiss();
                reset(fStatus, true, newAktJob);
            });
        }).start();
    }

    /*
     * Import Task - importiert Sicherungen aus "Arbeitszeiterfassung"
     */
    private void importTask(String filename) {
        final ProgressDialog mDialog = new ProgressDialog(mContext);

        // Fortschritsdialog öffnen
        mDialog.setIndeterminate(true);
        mDialog.setIndeterminateDrawable(
                ResourcesCompat.getDrawable(
                        getResources(),
                        R.drawable.progress_dialog_anim,
                        Objects.requireNonNull(mContext).getTheme()));
        mDialog.setMessage(getString(R.string.mig_prog_import));
        mDialog.setCancelable(false);
        mDialog.show();

        Handler mHandler = new Handler();
        new Thread(() -> {
            long aktJob = 0;
            boolean mStatus = false;
            SQLiteOpenHelper arbeitszeitDB = new Datenbank_toMigrate(mContext);
            Datenbank_Migrate mMigradeDB = new Datenbank_Migrate(arbeitszeitDB, mStorageHelper, mContext);
            try {
                // Datenbank neu anlegen
                ASettings.resetDatenbank(mContext);
                // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
                // Einstellungen einlesen und Migration beginnen
                mMigradeDB.einlesen(filename);
                mHandler.post(() -> mDialog.setMessage(ASettings.res.getString(R.string.mig_prog_einstellungen)));
                aktJob = mMigradeDB.Migrate_Einstellungen(ASettings.mDatenbank);
                mHandler.post(() -> mDialog.setMessage(ASettings.res.getString(R.string.mig_prog_arbeitsplatz)));
                aktJob= mMigradeDB.Migrate_Arbeitsplatz(ASettings.mDatenbank, aktJob);
                mHandler.post(() -> mDialog.setMessage(ASettings.res.getString(R.string.mig_prog_eort)));
                mMigradeDB.Migrate_Eorte();
                mHandler.post(() -> mDialog.setMessage(ASettings.res.getString(R.string.mig_prog_zeit)));
                mMigradeDB.Migrate_Zeiten(ASettings.mDatenbank);
                mMigradeDB.Delete_AlteDB();

                // ASettings.mDatenbank.close();
                mStatus = true;
            } catch (Exception e) {
                e.printStackTrace();
            }

            final long newAktJob = aktJob;
            final boolean fStatus = mStatus;
            mHandler.post(() -> {
                // Fortschrittsdialog schliessen
                mDialog.dismiss();
                reset(fStatus, false, newAktJob);
            });
        }).start();
    }

    @SuppressLint("Range")
    private void reset(boolean status, boolean isKonto, long aktJob) {
        // SQLiteDatabase mDatenbank = ASettings.stundenDBHelper.getWritableDatabase();
        SharedPreferences.Editor mEdit = ASettings.mPreferenzen.edit();
        // den Initprozess als beendet markieren
        mEdit.putBoolean(ISettings.KEY_INIT_FINISH, true).apply();

        if (isKonto) {
            // Allgemeine Einstellungen wiederherstellen
            String mSQL;
            Cursor mResult;

            mSQL = "SELECT * FROM " + DatenbankHelper.DB_T_SETTINGS +
                    " WHERE " + DatenbankHelper.DB_F_ID + "=1 LIMIT 1 ";

            mResult = ASettings.mDatenbank.rawQuery(mSQL, null);

            if (mResult.getCount() > 0) {
                int mOptionen;
                mResult.moveToFirst();

                mEdit.putLong(ISettings.KEY_JOBID, mResult.getLong(mResult.getColumnIndex(DatenbankHelper.DB_F_JOB))).commit();
                mEdit.putString(ISettings.KEY_USERNAME, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_USER)));
                mEdit.putString(ISettings.KEY_USERANSCHRIFT, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_ANSCHRIFT)));
                mEdit.putString(ISettings.KEY_ANZEIGE_W_KUERZEL, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_W_KUERZEL)));
                //mEdit.putString(ISetup.KEY_ANZEIGE_W_TRENNER, mResult.getString(mResult.getColumnIndex(Datenbank.DB_F_W_TRENNER)));
                mEdit.putString(ISettings.KEY_ANZEIGE_E_KUERZEL, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_E_KUERZEL)));
                mEdit.putInt(ISettings.KEY_ANZEIGE_VIEW, mResult.getInt(mResult.getColumnIndex(DatenbankHelper.DB_F_VIEW)));
                mEdit.putString(ISettings.KEY_DATEN_DIR, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_DATEN_DIR)));
                if (mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_BACKUP_DIR)) == null)
                    mEdit.putString(ISettings.KEY_BACKUP_DIR, mResult.getString(mResult.getColumnIndex(DatenbankHelper.DB_F_BACKUP_DIR)));

                mOptionen = mResult.getInt(mResult.getColumnIndex(DatenbankHelper.DB_F_OPTIONEN));

                // die Option "dezimale Minutenanzeige" ist seit V 1.02.94 in die Arbeitsplatzeinstellungen gewandert
                if (mResult.getInt(mResult.getColumnIndex(DatenbankHelper.DB_F_VERSION)) < 10294) {
                    boolean dezimal = ((mOptionen & ISettings.OPT_ANZ_DEZIMAL) != 0);
                    //ArbeitsplatzListe aListe = new ArbeitsplatzListe(null);
                    ArbeitsplatzListe aListe = ASettings.jobListe;
                    for (Arbeitsplatz a : aListe.getListe()) {
                        a.setOption(Arbeitsplatz.OPT_ANZEIGE_DEZIMAL, dezimal);
                        a.schreibeJob();
                    }
                }
                mEdit.putBoolean(ISettings.KEY_ANZEIGE_ERW_SALDO, ((mOptionen & ISettings.OPT_ANZ_ERW_SALDO) != 0));
                mEdit.putBoolean(ISettings.KEY_ANZEIGE_UMG_SORT, ((mOptionen & ISettings.OPT_ANZ_UMG_SORT) != 0));
                mEdit.putBoolean(ISettings.KEY_THEMA_DUNKEL, ((mOptionen & ISettings.OPT_ANZ_THEMA_DUNKEL) != 0));

                mEdit.apply();

                if (!mResult.isNull(mResult.getColumnIndex(DatenbankHelper.DB_F_SPRACHE))) {
                    String s = LocaleHelper.getLanguage(mContext);

                    switch (s) {
                        case "it":
                            LocaleHelper.setLocale(mContext.getApplicationContext(), "it", Locale.getDefault().getCountry());
                            break;
                        case "de":
                            LocaleHelper.setLocale(mContext.getApplicationContext(), "de", Locale.getDefault().getCountry());
                            break;
                        default:
                            LocaleHelper.setLocale(mContext.getApplicationContext(), "en", Locale.getDefault().getCountry());
                    }
                }

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

            // Toast ausgeben
            Toast toast = Toast.makeText(
                    mContext,
                    status ?
                            getString(R.string.restore_toast_erfolg) :
                            getString(R.string.restore_toast_misserfolg),
                    Toast.LENGTH_LONG);
            toast.show();

            ASettings.zustand = ISettings.INIT_ZUSTAND_UNGELADEN;
            // alten Zustand der App wieder anzeigen
            mEdit.putBoolean(ISettings.KEY_RESUME_VIEW, true).apply();

            Intent mMainIntent = new Intent();
            mMainIntent.setAction(ISettings.APP_RESET);
            mMainIntent.setClass(mContext, MainActivity.class);
            mMainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(mMainIntent);
        } else {
            //mCallback.onMigrationDone(status);
            if(status) {
                mEdit.putLong(KEY_JOBID, aktJob).apply();

                Intent mSettingsIntent = new Intent();
                mSettingsIntent.setAction(ISettings.APP_RESET);
                mSettingsIntent.setClass(mContext, SettingsActivity.class);
                mSettingsIntent.putExtra(ISettings.KEY_EDIT_JOB, aktJob);
                mSettingsIntent.putExtra(ISettings.KEY_INIT_SEITE, ISettings.SETUP_SEITE_ALLGEMEIN);
                mSettingsIntent.putExtra(ISettings.ARG_IS_INITASSIST, true);
                mSettingsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mSettingsIntent);
            }
        }
    }
}
