package it.integry.integrywmsnative.view.dialogs.input_quantity_v2;

import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.text.InputType;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.databinding.ObservableField;
import androidx.fragment.app.DialogFragment;

import com.google.android.material.textfield.TextInputLayout;
import com.pedromassango.doubleclick.DoubleClick;
import com.pedromassango.doubleclick.DoubleClickListener;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;

import javax.inject.Inject;
import javax.inject.Singleton;

import it.integry.barcode_base_android_library.model.BarcodeScanDTO;
import it.integry.integrywmsnative.MainApplication;
import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeCallbackDTO;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeManager;
import it.integry.integrywmsnative.core.expansion.BaseDialogFragment;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.expansion.RunnableArgss;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.model.MtbUntMis;
import it.integry.integrywmsnative.core.model.secondary.StatoPartitaMag;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.core.utility.UtilityFocus;
import it.integry.integrywmsnative.core.utility.UtilityObservable;
import it.integry.integrywmsnative.databinding.DialogInputQuantityV2Binding;
import it.integry.integrywmsnative.view.dialogs.base.DialogSimpleMessageView;

@Singleton
public class DialogInputQuantityV2View extends BaseDialogFragment implements DialogInputQuantityV2ViewModel.Listener {

    @Inject
    DialogInputQuantityV2ViewModel mViewModel;

    private DialogInputQuantityV2DTO mDialogInputQuantityV2DTO;
    private RunnableArgss<DialogInputQuantityV2ResultDTO, Boolean> mOnComplete;
    private Runnable mOnAbort;

    public ObservableField<Integer> currentTextNumCnfToTake = new ObservableField<>(0);
    public ObservableField<Boolean> flagShowCnfToTakeLabel = new ObservableField<>(true);
    public ObservableField<Integer> currentTextNumPezziToTake = new ObservableField<>(0);

    public ObservableField<String> currentPartitaMag = new ObservableField<>();
    public ObservableField<String> currentNotes = new ObservableField<>();
    public ObservableField<Date> currentDataScad = new ObservableField<>();

    public ObservableField<BigDecimal> currentNumCnf = new ObservableField<>();
    public ObservableField<BigDecimal> currentQtaCnf = new ObservableField<>();
    public ObservableField<BigDecimal> currentQtaTot = new ObservableField<>();

    public ObservableField<BigDecimal> currentTaraTot = new ObservableField<>();
    public ObservableField<BigDecimal> currentTaraArticolo = new ObservableField<>();
    public ObservableField<BigDecimal> currentPesoLordo = new ObservableField<>();

    public ObservableField<Boolean> enabledNumCnf = new ObservableField<>(true);
    public ObservableField<Boolean> enabledQtaCnf = new ObservableField<>(true);
    public ObservableField<Boolean> enabledQtaTot = new ObservableField<>(true);
    public ObservableField<Boolean> enabledPesoLordo = new ObservableField<>(false);

    public ObservableField<Boolean> enabledChangePartitaMag = new ObservableField<>(true);
    public ObservableField<Boolean> enabledNotes = new ObservableField<>(false);
    public ObservableField<Boolean> enabledLUCloseButton = new ObservableField<>(true);
    public ObservableField<Boolean> showProductLotStatus = new ObservableField<>(false);

    private final Handler mHandler = new Handler();

    private Context context;

    private DialogInputQuantityV2Binding mBindings;
    private boolean mEnableDataCallback = true;
    private boolean mObservablesInitated = false;

    private int mBarcodeScannerIstanceID;
    private boolean mAbort = true;


    public DialogInputQuantityV2View setDialogInputQuantityV2DTO(DialogInputQuantityV2DTO mDialogInputQuantityV2DTO) {
        this.mDialogInputQuantityV2DTO = mDialogInputQuantityV2DTO;
        return this;
    }

    public DialogInputQuantityV2View setOnComplete(RunnableArgss<DialogInputQuantityV2ResultDTO, Boolean> mOnComplete) {
        this.mOnComplete = mOnComplete;
        return this;
    }

    public DialogInputQuantityV2View setOnAbort(Runnable mOnAbort) {
        this.mOnAbort = mOnAbort;
        return this;
    }

    public DialogInputQuantityV2View() {
        super();
//        openInFullScreen();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme_NewMaterial_Dialog_FullscreenDialog);
        this.initBarcode();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        var dialog = super.onCreateDialog(savedInstanceState);
        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        this.context = getActivity();

        mBindings = DialogInputQuantityV2Binding.inflate(inflater, container, false);
        mBindings.setLifecycleOwner(this);
        mBindings.toolbar.setTitle("Inserimento articolo");

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

        this.mViewModel
                .setMtbAart(mDialogInputQuantityV2DTO.getMtbAart())
                .setInitialNumCnf(mDialogInputQuantityV2DTO.getInitialNumCnf())
                .setInitialQtaCnf(mDialogInputQuantityV2DTO.getInitialQtaCnf())
                .setInitialQtaTot(mDialogInputQuantityV2DTO.getInitialQtaTot())
                .setTotalQtaInWarehouse(mDialogInputQuantityV2DTO.getTotalQtaInWarehouse())
                .setTotalNumCnfInWarehouse(mDialogInputQuantityV2DTO.getTotalNumCnfInWarehouse())
                .setTotalQtaCommitted(mDialogInputQuantityV2DTO.getTotalQtaCommitted())
                .setTotalNumCnfCommitted(mDialogInputQuantityV2DTO.getTotalNumCnfCommitted())
                .setTotalNumCnfOrd(mDialogInputQuantityV2DTO.getTotalNumCnfOrd())
                .setTotalQtaOrd(mDialogInputQuantityV2DTO.getTotalQtaOrd())
                .setQtaCnfOrd(mDialogInputQuantityV2DTO.getQtaCnfOrd())
                .setTotalNumCnfToBeTaken(mDialogInputQuantityV2DTO.getTotalNumCnfToBeTaken())
                .setTotalQtaToBeTaken(mDialogInputQuantityV2DTO.getTotalQtaToBeTaken())
                .setQtaCnfToBeTaken(mDialogInputQuantityV2DTO.getQtaCnfToBeTaken())
                .setTotalNumCnfAvailable(mDialogInputQuantityV2DTO.getTotalNumCnfAvailable())
                .setTotalQtaAvailable(mDialogInputQuantityV2DTO.getTotalQtaAvailable())
                .setCanOverflowOrderQuantity(mDialogInputQuantityV2DTO.isCanOverflowOrderQuantity())
                .setQtaCnfAvailable(mDialogInputQuantityV2DTO.getQtaCnfAvailable())
                .setPartitaMag(mDialogInputQuantityV2DTO.getPartitaMag())
                .setNote(mDialogInputQuantityV2DTO.getNote())
                .setIsNoteMandatory(mDialogInputQuantityV2DTO.isNotesMandatory())
                .setSuggestPartitaMagRunnable(mDialogInputQuantityV2DTO.getSuggestPartitaMag())
                .setDataScad(mDialogInputQuantityV2DTO.getDataScad());

        mBindings.setView(this);
        mBindings.setViewmodel(this.mViewModel);

        if (mDialogInputQuantityV2DTO.isNotifyProductLotStatus() && mDialogInputQuantityV2DTO.getStatoPartitaMag() != null) {
            this.initProductLotStatusNotification();
        }

        MtbUntMis mtbUntMis = mDialogInputQuantityV2DTO.getMtbAart().getMtbUntMis() != null && mDialogInputQuantityV2DTO.getMtbAart().getMtbUntMis().size() > 0 ? mDialogInputQuantityV2DTO.getMtbAart().getMtbUntMis().get(0) : null;
        if (!(mtbUntMis != null && mtbUntMis.isFlagDig())) {
            mBindings.inputQtaTotText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        }


        if (mDialogInputQuantityV2DTO.isSaveOnImeDone()) {

            mBindings.inputNumCnfText.setOnEditorActionListener((v, actionId, event) -> {
                if (actionId == EditorInfo.IME_ACTION_DONE) {
                    save();
                    return true;
                }
                return false;
            });
        }
        this.onLoadingEnded();

        if (mDialogInputQuantityV2DTO.isFocusOnStart()) {
            getDialog().setOnShowListener(dialog -> {
                if (mDialogInputQuantityV2DTO.isNumCnfEditable()) {
                    UtilityFocus.focusTextBox(requireContext(), mBindings.inputNumCnfText);
                } else {
                    UtilityFocus.focusTextBox(requireContext(), mBindings.inputQtaTotText);
                }
            });
        }
        return mBindings.getRoot();
    }

    private void initProductLotStatusNotification() {
        StatoPartitaMag statoPartitaMag = StatoPartitaMag.from(this.mDialogInputQuantityV2DTO.getStatoPartitaMag().getStatoArt());
        if (statoPartitaMag == null)
            return;

        this.mBindings.inputDataScadLayout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM);
        switch (statoPartitaMag) {
            case SCADUTO:
                this.mBindings.inputDataScadLayout.setEndIconDrawable(R.drawable.ic_baseline_warning_24);
                this.mBindings.inputDataScadLayout.setEndIconTintList(ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.warn_color)));
                break;
            case IN_SCADENZA:
                this.mBindings.inputDataScadLayout.setEndIconDrawable(R.drawable.ic_baseline_warning_24);
                this.mBindings.inputDataScadLayout.setEndIconTintList(ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.error_color)));
                break;
            default:
                this.mBindings.inputDataScadLayout.setEndIconDrawable(R.drawable.ic_check_white_24dp);
                this.mBindings.inputDataScadLayout.setEndIconTintList(ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.success_color)));

        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        BarcodeManager.removeCallback(mBarcodeScannerIstanceID);
        if (mAbort) this.mOnAbort.run();
    }

    private void initBarcode() {
        mBarcodeScannerIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO()
                .setOnScanSuccessful(onScanSuccessful)
                .setOnScanFailed(ex -> UtilityExceptions.defaultException(this.context, ex, false)));
    }

    private final RunnableArgs<BarcodeScanDTO> onScanSuccessful = data -> {
        this.onLoadingStarted();

        this.mViewModel.processBarcodeDTO(data, this::onLoadingEnded);
    };

    public void save() {
        if (this.mViewModel.validate()) {
            this.mAbort = false;
            dismiss();
            this.mOnComplete.run(this.mViewModel.getResult(), false);
        }
    }

    public void saveAndCloseLU() {
        if (this.mViewModel.validate()) {
            this.mAbort = false;
            dismiss();
            this.mOnComplete.run(this.mViewModel.getResult(), true);
        }
    }

//    @Override
//    public void onDismiss(@NonNull DialogInterface dialog) {
//        BarcodeManager.removeCallback(mBarcodeScannerIstanceID);
//        if (mAbort) this.mOnAbort.run();
//        super.onDismiss(dialog);
//    }

    @Override
    public void onStart() {
        super.onStart();

        this.init();

        int onNumCnfInputChanged = SettingsManager.iDB().getOnNumCnfInputChanged();
        int onQtaTotInputChanged = SettingsManager.iDB().getOnQtaTotInputChanged();

        this.mViewModel.setListener(this);
        this.mViewModel.init(onNumCnfInputChanged, onQtaTotInputChanged);
    }

    private void initViewObservables() {

        UtilityObservable.addPropertyChanged(this.currentPartitaMag, (value) -> {
            if (this.mEnableDataCallback) {
                this.mViewModel.setPartitaMag(value);
            }
        });

        UtilityObservable.addPropertyChanged(this.currentDataScad, (value) -> {
            if (this.mEnableDataCallback) {
                MtbAart mtbAart = this.mViewModel.getMtbAart();
                if (value != null && mtbAart != null && mtbAart.getGgScadPartita() != null && mtbAart.getGgScadPartita() > 0) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.add(Calendar.DATE, mtbAart.getGgScadPartita());
                    Date minDataScad = calendar.getTime();
                    if (minDataScad.after(value) && value.after(new Date())) {
                        DialogSimpleMessageView
                                .makeWarningDialog(new SpannableString("La data selezionata è precedente alla data di scadenza consigliata per l'articolo scelto ( " + mtbAart.getGgScadPartita() + " giorni) . Continuare?"), null, () -> this.mViewModel.setDataScad(value), () -> this.currentDataScad.set(null))
                                .show(requireActivity().getSupportFragmentManager(), "tag");
                    } else {
                        this.mViewModel.setDataScad(value);
                    }
                } else {
                    this.mViewModel.setDataScad(value);
                }

            }
        });

        UtilityObservable.addPropertyChanged(this.currentNotes, (value) -> {
            if (this.mEnableDataCallback) {
                this.mViewModel.setNote(value);
            }
        });

        UtilityObservable.addPropertyChanged(this.currentNumCnf, (value) -> {
            if (this.mEnableDataCallback) {
                this.mViewModel.setNumCnf(value);
            }
        });

        UtilityObservable.addPropertyChanged(this.currentQtaCnf, (value) -> {
            if (this.mEnableDataCallback) {
                this.mViewModel.setQtaCnf(value);
            }
        });

        UtilityObservable.addPropertyChanged(this.currentQtaTot, (value) -> {
            if (this.mEnableDataCallback) {
                this.mViewModel.setQtaTot(value);
            }
        });


    }


    private void initViewModelObservables() {

        final ColorStateList textColorsNumCnf = this.mBindings.inputNumCnfLayout.getEditText().getTextColors();
        final ColorStateList textColorsQtaCnf = this.mBindings.inputQtaCnfLayout.getEditText().getTextColors();
        final ColorStateList textColorsQtaTot = this.mBindings.inputQtaTotLayout.getEditText().getTextColors();

        UtilityObservable.addPropertyChanged(this.mViewModel.blockedNumCnf, (value) -> {
            toggleTextInputLayoutError(textColorsNumCnf, this.mBindings.inputNumCnfLayout, value);

            if (this.mViewModel.mtbAart.get().isFlagQtaCnfFissaBoolean()) {
                this.enabledQtaTot.set(!value);
            } else {
                if (value) {
                    if (this.mViewModel.blockedQtaCnf.get()) {
                        this.enabledQtaTot.set(false);
                    } else if (this.mViewModel.blockedQtaTot.get()) {
                        this.enabledQtaCnf.set(false);
                    }
                } else {
                    if (!this.enabledQtaTot.get()) {
                        this.enabledQtaTot.set(true);
                    } else if (!this.enabledQtaCnf.get()) {
                        this.enabledQtaCnf.set(true);
                    }
                }
            }
        });

        UtilityObservable.addPropertyChanged(this.mViewModel.blockedQtaCnf, (value) -> {
            toggleTextInputLayoutError(textColorsQtaCnf, this.mBindings.inputQtaCnfLayout, value);

            if (value) {
                if (this.mViewModel.blockedNumCnf.get()) {
                    this.enabledQtaTot.set(false);
                } else if (this.mViewModel.blockedQtaTot.get()) {
                    this.enabledNumCnf.set(false);
                }
            } else {
                if (!this.enabledQtaTot.get()) {
                    this.enabledQtaTot.set(true);
                } else if (!this.enabledNumCnf.get()) {
                    this.enabledNumCnf.set(this.mDialogInputQuantityV2DTO.isNumCnfEditable());
                }
            }
        });

        UtilityObservable.addPropertyChanged(this.mViewModel.blockedQtaTot, (value) -> {
            toggleTextInputLayoutError(textColorsQtaTot, this.mBindings.inputQtaTotLayout, value);

            if (this.mViewModel.mtbAart.get().isFlagQtaCnfFissaBoolean()) {
                this.enabledNumCnf.set(this.mDialogInputQuantityV2DTO.isNumCnfEditable() && !value);
            } else {
                if (value) {
                    if (this.mViewModel.blockedQtaCnf.get()) {
                        this.enabledNumCnf.set(false);
                    } else if (this.mViewModel.blockedNumCnf.get()) {
                        this.enabledQtaCnf.set(false);
                    }
                } else {
                    if (!this.enabledQtaCnf.get()) {
                        this.enabledQtaCnf.set(true);
                    } else if (!this.enabledNumCnf.get()) {
                        this.enabledNumCnf.set(this.mDialogInputQuantityV2DTO.isNumCnfEditable());
                    }
                }
            }
        });
    }

    private void init() {
        if (!mObservablesInitated) {
            initViewObservables();
            mObservablesInitated = true;
        }

        initViewModelObservables();

        //Init double taps
        this.mBindings.inputNumCnfText.setOnClickListener(new DoubleClick(new DoubleClickListener() {
            @Override
            public void onSingleClick(View view) {
                String a = "";
            }

            @Override
            public void onDoubleClick(View view) {
                mViewModel.blockedNumCnf.set(!mViewModel.blockedNumCnf.get());
            }
        }));

        this.mBindings.inputQtaCnfText.setOnClickListener(new DoubleClick(new DoubleClickListener() {
            @Override
            public void onSingleClick(View view) {
                String a = "";
            }

            @Override
            public void onDoubleClick(View view) {
                mViewModel.blockedQtaCnf.set(!mViewModel.blockedQtaCnf.get());
            }
        }));

        this.mBindings.inputQtaTotText.setOnClickListener(new DoubleClick(new DoubleClickListener() {
            @Override
            public void onSingleClick(View view) {
                String a = "";
            }

            @Override
            public void onDoubleClick(View view) {
                mViewModel.blockedQtaTot.set(!mViewModel.blockedQtaTot.get());
            }
        }));


        this.mViewModel.setCanPartitaMagBeChanged(this.mDialogInputQuantityV2DTO.isCanPartitaMagBeChanged());
        this.enabledChangePartitaMag.set(this.mDialogInputQuantityV2DTO.isCanPartitaMagBeChanged());
        this.mViewModel.shouldAskDataScad = this.mDialogInputQuantityV2DTO.isDataScadMandatory();
        this.enabledNotes.set(this.mDialogInputQuantityV2DTO.isNotesAllowed());
        this.showProductLotStatus.set(SettingsManager.iDB().isNotifyLotStatus());
        this.enabledLUCloseButton.set(this.mDialogInputQuantityV2DTO.isCanLUBeClosed());
        this.currentTaraArticolo.set(this.mViewModel.getMtbAart().getTaraKg());

        if (this.mDialogInputQuantityV2DTO.getMtbAart().isFlagQtaCnfFissaBoolean() && this.mDialogInputQuantityV2DTO.getTotalQtaOrd() != null && !this.mDialogInputQuantityV2DTO.getTotalQtaOrd().equals(BigDecimal.ZERO) && !(this.mDialogInputQuantityV2DTO.getQtaCnfOrd().compareTo(BigDecimal.ZERO) == 0)) {
            int numCnftoTake = this.mDialogInputQuantityV2DTO.getTotalQtaOrd().divide(this.mDialogInputQuantityV2DTO.getQtaCnfOrd(), 0, RoundingMode.DOWN).intValue();
            this.currentTextNumCnfToTake.set(numCnftoTake);
            int qtaText = this.mDialogInputQuantityV2DTO.getTotalQtaOrd().remainder(this.mDialogInputQuantityV2DTO.getQtaCnfOrd()).intValue();
            this.currentTextNumPezziToTake.set(qtaText);
        } else {
            this.currentTextNumCnfToTake.set(0);
            this.currentTextNumPezziToTake.set(0);

        }

    }


    private void toggleTextInputLayoutError(ColorStateList originalColorStateList, TextInputLayout textInputLayout, boolean isError) {
        if (isError) {
            textInputLayout.setErrorEnabled(true);
            textInputLayout.setError(" ");
            textInputLayout.setErrorIconDrawable(null);
            textInputLayout.getEditText().setTextColor(ContextCompat.getColor(this.context, R.color.red_600));
            textInputLayout.setHintTextAppearance(R.style.ErrorFloatingLabel);
        } else {
            textInputLayout.setErrorEnabled(false);
            textInputLayout.setError(null);
            textInputLayout.getEditText().setTextColor(originalColorStateList);
            textInputLayout.setHintTextAppearance(R.style.NormalFloatingLabel);
        }
    }

    @Override
    public void onDataChanged() {
        this.mEnableDataCallback = false;

        this.currentPartitaMag.set(this.mViewModel.getPartitaMag());
        this.currentNotes.set(this.mViewModel.getNote());
        this.currentDataScad.set(this.mViewModel.getDataScad());
        this.currentNumCnf.set(this.mViewModel.getNumCnf());
        this.currentQtaCnf.set(this.mViewModel.getQtaCnf());
        this.currentQtaTot.set(this.mViewModel.getQtaTot());

        MtbAart articolo = this.mViewModel.getMtbAart();
        if (articolo != null && !articolo.isFlagQtaCnfFissaBoolean()) {
            BigDecimal taraTot = this.mViewModel.getNumCnf().multiply(articolo.getTaraKg());
            this.currentTaraTot.set(taraTot);
            this.currentPesoLordo.set(this.mViewModel.getQtaTot().add(taraTot));
            this.flagShowCnfToTakeLabel.set(false);
        }

        this.mBindings.executePendingBindings();

        this.mEnableDataCallback = true;
    }

    @Override
    public void onError(Exception ex) {
        DialogSimpleMessageView
                .makeErrorDialog(new SpannableString(Html.fromHtml(ex.getMessage())), null, null)
                .show(requireActivity().getSupportFragmentManager(), "tag");
    }
}
