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

import android.app.ProgressDialog;
import android.content.Context;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.appcompat.app.AlertDialog;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;

import com.annimon.stream.Stream;

import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.REST.consumers.BarcodeRESTConsumer;
import it.integry.integrywmsnative.core.REST.consumers.ColliMagazzinoRESTConsumer;
import it.integry.integrywmsnative.core.REST.consumers.PosizioneRESTonsumer;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeCallbackDTO;
import it.integry.integrywmsnative.core.barcode_reader.BarcodeManager;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.model.MtbDepoPosizione;
import it.integry.integrywmsnative.core.model.secondary.GestioneEnum;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityBarcode;
import it.integry.integrywmsnative.core.utility.UtilityExceptions;
import it.integry.integrywmsnative.core.utility.UtilityProgress;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.databinding.DialogScanOrCreateLuBinding;
import it.integry.integrywmsnative.view.dialogs.DialogSimpleMessageHelper;
import it.integry.plugins.barcode_base_library.model.BarcodeScanDTO;

public class DialogScanOrCreateLU {

    private Context currentContext;

    private AlertDialog currentAlert;

    private DialogScanOrCreateLuBinding mBinding;

    private RunnableArgs<MtbColt> mOnDialogDismiss;

    private MtbColt currentMtbColt;


    public static AlertDialog make(final Context context, RunnableArgs<MtbColt> onDialogDismiss) {
        return new DialogScanOrCreateLU(context, false, onDialogDismiss).currentAlert;
    }

    public static AlertDialog make(final Context context, boolean disableCreation, RunnableArgs<MtbColt> onDialogDismiss) {
        return new DialogScanOrCreateLU(context, disableCreation, onDialogDismiss).currentAlert;
    }

    private DialogScanOrCreateLU(Context context, boolean disableCreation, RunnableArgs<MtbColt> onDialogDismiss) {
        mOnDialogDismiss = null;
        currentMtbColt = null;

        currentContext = context;

        LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );

        mBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_scan_or_create_lu, null, false);

        if(disableCreation) mBinding.dialogScanOrCreateLuCreationLayout.setVisibility(View.GONE);

        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context)
                .setView(mBinding.getRoot());

        currentAlert = alertDialog.create();
        currentAlert.setCanceledOnTouchOutside(false);

        init(onDialogDismiss);
        initBarcode(context);
    }


    private void init(RunnableArgs<MtbColt> onDialogDismiss) {
        mOnDialogDismiss = onDialogDismiss;

        mBinding.createNewLuButton.setOnClickListener(v -> {
            final ProgressDialog progressDialog = UtilityProgress.createDefaultProgressDialog(currentContext);

            ColliMagazzinoRESTConsumer.createColloLavorazione(+1, createdMtbColt -> {
                sendMtbColt(createdMtbColt, progressDialog);
            }, ex -> {
                UtilityExceptions.defaultException(currentContext, ex, progressDialog);
            });
        });
    }

    private void initBarcode(Context context) {

        int barcodeIstanceID = BarcodeManager.addCallback(new BarcodeCallbackDTO()
                .setOnScanSuccessfull(onScanSuccessfull)
                .setOnScanFailed(ex -> UtilityExceptions.defaultException(context, ex, false)));

        currentAlert.setOnDismissListener(dialog -> {
            BarcodeManager.removeCallback(barcodeIstanceID);
            BarcodeManager.enable();
            if(currentMtbColt == null) {
                mOnDialogDismiss.run(null);
            }
        });

    }


    private RunnableArgs<BarcodeScanDTO> onScanSuccessfull = data -> {
        BarcodeManager.disable();

        final ProgressDialog progressDialog = UtilityProgress.createDefaultProgressDialog(currentContext);

        if(UtilityBarcode.isEtichettaPosizione(data)){
            this.executeEtichettaPosizione(data, progressDialog);
        } else if(UtilityBarcode.isEtichettaAnonima(data)) {
            this.executeEtichettaAnonima(data, progressDialog);
        } else if(UtilityBarcode.isEtichetta128(data)) {
            this.executeEAN128(data, progressDialog);
        } else {
            progressDialog.dismiss();
            BarcodeManager.enable();
            showNoULFound();
        }

    };

    private void executeEtichettaPosizione(BarcodeScanDTO barcodeScanDTO, ProgressDialog progressDialog) {

        MtbDepoPosizione foundPosizione = Stream.of(SettingsManager.iDB().getAvailablePosizioni())
                .filter(x -> x.getPosizione().equalsIgnoreCase(barcodeScanDTO.getStringValue()))
                .single();

        PosizioneRESTonsumer.getBancaliInPosizione(foundPosizione, mtbColtList -> {

            if(mtbColtList == null || mtbColtList.size() == 0){
                progressDialog.dismiss();
                BarcodeManager.enable();
                showNoULFound();
            } else if (mtbColtList.size() == 1) {
                ColliMagazzinoRESTConsumer.getByTestata(mtbColtList.get(0), true, false, mtbColt -> {
                    sendMtbColt(mtbColt, progressDialog);
                }, ex ->  {
                    UtilityExceptions.defaultException(currentContext, ex, progressDialog);
                    BarcodeManager.enable();
                });



            } else {
                progressDialog.dismiss();
                BarcodeManager.enable();
                showTooMuchULFound();
            }

        }, ex -> {
            UtilityExceptions.defaultException(currentContext, ex, progressDialog);
            BarcodeManager.enable();
        });

    }


    private void executeEtichettaAnonima(BarcodeScanDTO barcodeScanDTO, ProgressDialog progressDialog) {
        ColliMagazzinoRESTConsumer.getBySSCC(barcodeScanDTO.getStringValue(), true, false, mtbColt -> {

            if(mtbColt == null) {

                ColliMagazzinoRESTConsumer.createColloFromEtichettaAnonima(barcodeScanDTO, GestioneEnum.LAVORAZIONE, createdMtbColt -> {
                    BarcodeManager.enable();
                    createdMtbColt.setDisablePrint(true);
                    sendMtbColt(createdMtbColt, progressDialog);
                }, ex -> {
                    UtilityExceptions.defaultException(currentContext, ex, progressDialog);
                    BarcodeManager.enable();
                });

            } else {

                BarcodeManager.enable();

                mtbColt.setDisablePrint(true);
                sendMtbColt(mtbColt, progressDialog);

            }

        }, ex -> {
            UtilityExceptions.defaultException(currentContext, ex, progressDialog);
            BarcodeManager.enable();
        });
    }


    private void executeEAN128(BarcodeScanDTO barcodeScanDTO, ProgressDialog progressDialog) {
        BarcodeRESTConsumer.decodeEan128(barcodeScanDTO, ean128Model -> {

            if(ean128Model != null && !UtilityString.isNullOrEmpty(ean128Model.Sscc)) {

                ColliMagazzinoRESTConsumer.getBySSCC(ean128Model.Sscc, true, false, mtbColt -> {

                    if(mtbColt != null) {

                        BarcodeManager.enable();
                        sendMtbColt(mtbColt, progressDialog);

                    } else {
                        BarcodeManager.enable();
                        progressDialog.dismiss();
                        showNoULFound();
                    }

                }, ex -> {
                    UtilityExceptions.defaultException(currentContext, ex, progressDialog);
                    BarcodeManager.enable();
                });

            } else {
                BarcodeManager.enable();
                progressDialog.dismiss();

                showNoULFound();
            }




        }, ex -> {
            UtilityExceptions.defaultException(currentContext, ex, progressDialog);
            BarcodeManager.enable();
        });
    }


    private void showTooMuchULFound() {
        DialogSimpleMessageHelper.makeWarningDialog(currentContext,
                new SpannableString(currentContext.getResources().getText(R.string.too_much_lu_found_message)),
                null, null).show();
    }

    private void showNoULFound() {
        DialogSimpleMessageHelper.makeWarningDialog(currentContext,
                new SpannableString(currentContext.getResources().getText(R.string.no_lu_found_message)),
                null, null).show();
    }

    private void sendMtbColt(MtbColt mtbColtToSend, ProgressDialog progressDialog) {
        currentMtbColt = mtbColtToSend;
        progressDialog.dismiss();
        currentAlert.dismiss();
        mOnDialogDismiss.run(mtbColtToSend);
    }

}
