package it.integry.integrywmsnative.gest.contab_doc_interni.dialog;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.ObservableField;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;

import java.util.Date;

import javax.inject.Inject;

import it.integry.integrywmsnative.MainApplication;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.expansion.BaseDialogFragment;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityObservable;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.databinding.DialogSelectDocInfoViewBinding;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.adapter.DialogSelectDocInfo_FornitoreAdapter;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.adapter.DialogSelectDocInfo_GroupArtAdapter;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.adapter.DialogSelectDocInfo_NoteAdapter;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.adapter.DialogSelectDocInfo_TipoDocAdapter;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.exception.DocumentRequiredException;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.exception.FornitoreRequiredException;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.exception.NoteRequiredException;
import it.integry.integrywmsnative.gest.contab_doc_interni.dialog.exception.TipoDocRequiredException;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.DocInterniSetupDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.FornitoreDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.GruppoArticoloDTO;
import it.integry.integrywmsnative.gest.contab_doc_interni.dto.TipoDocDTO;

public class DialogSelectDocInfoView extends BaseDialogFragment {

    @Inject
    DialogSelectDocInfoViewModel mViewModel;

    private DialogSelectDocInfoViewBinding mBindings;
    private Context mContext;

    private final DocInterniSetupDTO mDocInputData;
    private final RunnableArgs<DialogSelectDocInfoResponseDTO> onConfirm;
    private final Runnable onAbort;

    private boolean completed = false;

    public ObservableField<TipoDocDTO> selectedTipoDoc = new ObservableField<>();
    public ObservableField<GruppoArticoloDTO> selectedGroupArt = new ObservableField<>();
    public ObservableField<FornitoreDTO> selectedFornitore = new ObservableField<>();
    public ObservableField<String> selectedNumDoc = new ObservableField<>();
    public ObservableField<Date> selectedDataDoc = new ObservableField<>();
    public ObservableField<String> selectedNote = new ObservableField<>();

    public ObservableField<Boolean> isFornitoreRequired = new ObservableField<>();
    public ObservableField<Boolean> isDocumentRequired = new ObservableField<>();
    public ObservableField<Boolean> isNoteRequired = new ObservableField<>();

    public static DialogSelectDocInfoView newInstance(DocInterniSetupDTO docInputData,
                                                      RunnableArgs<DialogSelectDocInfoResponseDTO> onConfirm,
                                                      Runnable onAbort) {
        return new DialogSelectDocInfoView(docInputData, onConfirm, onAbort);
    }

    private DialogSelectDocInfoView(DocInterniSetupDTO docInputData,
                                    RunnableArgs<DialogSelectDocInfoResponseDTO> onConfirm,
                                    Runnable onAbort) {
        super();

        this.mDocInputData = docInputData;
        this.onConfirm = onConfirm;
        this.onAbort = onAbort;
    }


    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        this.mContext = requireContext();

        MainApplication.appComponent
                .dialogSelectDocInfoNewViewComponent()
                .create()
                .inject(this);

        setCancelable(false);

        mBindings = DialogSelectDocInfoViewBinding.inflate(LayoutInflater.from(this.mContext), null, false);
        mBindings.setLifecycleOwner(this);
        mBindings.setView(this);

        mViewModel.setFornitori(mDocInputData.getFornitori());

        var alertDialog = new MaterialAlertDialogBuilder(this.mContext)
                .setView(mBindings.getRoot())
                .setCancelable(isCancelable())
                .setPositiveButton(R.string.confirm, (dialog, which) -> {
                    //Volutamente vuoto
                })
                .setNegativeButton(R.string.abort, (dialog, which) -> {
                    //Volutamente vuoto
                })
                .create();

        alertDialog.setOnShowListener(this);
        alertDialog.setCanceledOnTouchOutside(isCancelable());
        alertDialog.setOnDismissListener(this);


        return alertDialog;
    }

    @Override
    public void onShow(DialogInterface dialogInterface) {
        super.onShow(dialogInterface);

        var alertDialog = ((AlertDialog) dialogInterface);

        var positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
        positiveButton.setOnClickListener(view -> {
            try {
                mBindings.inputCodDtip.setErrorEnabled(false);
                mBindings.inputCodDtip.setError(null);
                mBindings.inputCodAnagForn.setErrorEnabled(false);
                mBindings.inputCodAnagForn.setError(null);
                mBindings.inputNumDocLayout.setErrorEnabled(false);
                mBindings.inputNumDoc.setError(null);
                mBindings.inputDataDocLayout.setErrorEnabled(false);
                mBindings.inputDataDoc.setError(null);
                mBindings.inputNoteLayout.setErrorEnabled(false);
                mBindings.inputNoteLayout.setError(null);

                mViewModel.validate();
                completed = true;
                alertDialog.dismiss();

                if (this.onConfirm != null)
                    this.onConfirm.run(new DialogSelectDocInfoResponseDTO()
                            .setTipoDoc(selectedTipoDoc.get())
                            .setFornitore(selectedFornitore.get())
                            .setGruppoArt(selectedGroupArt.get())
                            .setDataDoc(selectedDataDoc.get())
                            .setNumDoc(!UtilityString.isNullOrEmpty(selectedNumDoc.get()) ? Integer.parseInt(selectedNumDoc.get()) : null)
                            .setNote(selectedNote.get()));
            } catch (TipoDocRequiredException tipoDocRequiredException) {
                mBindings.inputCodDtip.setErrorEnabled(true);
                mBindings.inputCodDtip.setError("Campo richiesto");
            } catch (FornitoreRequiredException fornitoreRequiredException) {
                mBindings.inputCodAnagForn.setErrorEnabled(true);
                mBindings.inputCodAnagForn.setError("Campo richiesto");
            } catch (DocumentRequiredException documentRequiredException) {
                mBindings.inputNumDocLayout.setErrorEnabled(true);
                mBindings.inputNumDocLayout.setError("Campo richiesto");
                mBindings.inputDataDocLayout.setErrorEnabled(true);
                mBindings.inputDataDocLayout.setError("Campo richiesto");
            } catch (NoteRequiredException noteRequiredException) {
                mBindings.inputNoteLayout.setErrorEnabled(true);
                mBindings.inputNoteLayout.setError("Campo richiesto");
            }
        });


        var negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
        negativeButton.setOnClickListener(view -> {
            alertDialog.dismiss();
            if (this.onAbort != null) this.onAbort.run();
        });

        this.initBindings();
        this.initAdapters();
    }



    private void initBindings() {
        this.isFornitoreRequired.set(mViewModel.isFornitoreRequired().getValue());
        mViewModel.isFornitoreRequired().observe(this, val -> this.isFornitoreRequired.set(val));

        this.isDocumentRequired.set(mViewModel.isDocumentRequired().getValue());
        mViewModel.isDocumentRequired().observe(this, val -> this.isDocumentRequired.set(val));

        this.isNoteRequired.set(mViewModel.isNoteRequired().getValue());
        mViewModel.isNoteRequired().observe(this, val -> this.isNoteRequired.set(val));


        UtilityObservable.addPropertyChanged(this.selectedTipoDoc, mViewModel::setTipoDoc);
        UtilityObservable.addPropertyChanged(this.selectedGroupArt, mViewModel::setGruppoArt);
        UtilityObservable.addPropertyChanged(this.selectedFornitore, mViewModel::setFornitore);
        UtilityObservable.addPropertyChanged(this.selectedDataDoc, mViewModel::setDataDoc);
        UtilityObservable.addPropertyChanged(this.selectedNumDoc,
                value -> this.mViewModel.setNumDoc(UtilityString.isNullOrEmpty(value) ? null : Integer.parseInt(value)));
        UtilityObservable.addPropertyChanged(this.selectedNote, mViewModel::setNote);

        mViewModel.isFornitoreRequired()
                .observe(this, val -> {
                    if (!val) {
                        this.selectedFornitore.set(null);
                        mBindings.filledExposedDropdownCodAnagList.setText("");
                    }
                });

        mViewModel.isNoteRequired()
                .observe(this, val -> {
                    if (!val) {
                        this.selectedNote.set(null);
                        mBindings.filledExposedDropdownNote.setText("");
                    }
                });
    }

    private void initAdapters() {
        var arrayAdapterCodDtips = new DialogSelectDocInfo_TipoDocAdapter(mContext, R.layout.array_adapter_single_item, mDocInputData.getTipiDoc());
        mBindings.filledExposedDropdownCodDtips.setAdapter(arrayAdapterCodDtips);
        mBindings.filledExposedDropdownCodDtips.setOnItemClickListener((adapterView, view, i, l) -> {
            this.selectedTipoDoc.set(
                    ((DialogSelectDocInfo_TipoDocAdapter.ListModel) adapterView.getItemAtPosition(i))
                            .getOriginalModel());
        });

        var arrayAdapterCodMgrps = new DialogSelectDocInfo_GroupArtAdapter(mContext, R.layout.array_adapter_single_item, mDocInputData.getGruppiArt());
        mBindings.filledExposedDropdownCodMgrps.setAdapter(arrayAdapterCodMgrps);
        mBindings.filledExposedDropdownCodMgrps.setOnItemClickListener((adapterView, view, i, l) -> {
            this.selectedGroupArt.set(
                    ((DialogSelectDocInfo_GroupArtAdapter.ListModel) adapterView.getItemAtPosition(i))
                            .getOriginalModel());
        });

        var arrayAdapterFornitori = new DialogSelectDocInfo_FornitoreAdapter(mContext, R.layout.array_adapter_single_item, mViewModel.getAvailableFornitori());
        mBindings.filledExposedDropdownCodAnagList.setAdapter(arrayAdapterFornitori);
        mBindings.filledExposedDropdownCodAnagList.setOnItemClickListener((adapterView, view, i, l) -> {
            this.selectedFornitore.set(
                    ((DialogSelectDocInfo_FornitoreAdapter.ListModel) adapterView.getItemAtPosition(i))
                            .getOriginalModel());
        });

        var arrayAdapterNote = new DialogSelectDocInfo_NoteAdapter(mContext, R.layout.array_adapter_single_item, SettingsManager.iDB().getNotePerditaDocInterni());
        mBindings.filledExposedDropdownNote.setAdapter(arrayAdapterNote);
    }

    @Override
    public void onDismiss(@NonNull DialogInterface dialog) {
        super.onDismiss(dialog);

        if(!completed)
            this.onAbort.run();
    }
}