package it.integry.integrywmsnative.gest.rettifica_giacenze;

import com.annimon.stream.Stream;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.inject.Inject;

import it.integry.barcode_base_android_library.model.BarcodeScanDTO;
import it.integry.integrywmsnative.core.exception.NoArtsFoundException;
import it.integry.integrywmsnative.core.exception.NoResultFromBarcodeException;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.expansion.RunnableArgss;
import it.integry.integrywmsnative.core.interfaces.viewmodel_listeners.ILUPositionListener;
import it.integry.integrywmsnative.core.interfaces.viewmodel_listeners.ILUPrintListener;
import it.integry.integrywmsnative.core.model.CommonModelConsts;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.model.MtbColr;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.model.MtbDepoPosizione;
import it.integry.integrywmsnative.core.model.dto.PickDataDTO;
import it.integry.integrywmsnative.core.rest.consumers.ArticoloRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.BarcodeRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.ColliMagazzinoRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.PrinterRESTConsumer;
import it.integry.integrywmsnative.core.rest.model.Ean13PesoModel;
import it.integry.integrywmsnative.core.utility.UtilityBarcode;
import it.integry.integrywmsnative.core.utility.UtilityBigDecimal;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.gest.rettifica_giacenze.dto.FornitoreDTO;
import it.integry.integrywmsnative.gest.rettifica_giacenze.rest.RettificaGiacenzeRESTConsumer;
import it.integry.integrywmsnative.gest.spedizione.exceptions.InvalidPesoKGException;
import it.integry.integrywmsnative.gest.spedizione.model.PickedQuantityDTO;
import it.integry.integrywmsnative.gest.spedizione.model.PickingObjectDTO;

public class RettificaGiacenzeViewModel {

    public MtbColt mCurrentMtbColt = null;

    private final ArticoloRESTConsumer mArticoloRESTConsumer;
    private final ColliMagazzinoRESTConsumer mColliMagazzinoRESTConsumer;
    private final PrinterRESTConsumer mPrinterRESTConsumer;
    private final BarcodeRESTConsumer mBarcodeRESTConsumer;
    private final RettificaGiacenzeRESTConsumer mRettificaGiacenzeRESTConsumer;

    private RettificaGiacenzeViewModel.Listener mListener;

    private String mCurrentUser;
    private String mCurrentCodMdep;
    private boolean mIsCreatedLU;

    private boolean mAnyEditDone = false;

    @Inject
    public RettificaGiacenzeViewModel(ArticoloRESTConsumer articoloRESTConsumer,
                                      ColliMagazzinoRESTConsumer colliMagazzinoRESTConsumer,
                                      PrinterRESTConsumer printerRESTConsumer,
                                      BarcodeRESTConsumer barcodeRESTConsumer,
                                      RettificaGiacenzeRESTConsumer rettificaGiacenzeRESTConsumer) {
        this.mArticoloRESTConsumer = articoloRESTConsumer;
        this.mColliMagazzinoRESTConsumer = colliMagazzinoRESTConsumer;
        this.mPrinterRESTConsumer = printerRESTConsumer;
        this.mBarcodeRESTConsumer = barcodeRESTConsumer;
        this.mRettificaGiacenzeRESTConsumer = rettificaGiacenzeRESTConsumer;
    }


    public void init(String currentUser, String currentCodMdep) {
        this.mCurrentUser = currentUser;
        this.mCurrentCodMdep = currentCodMdep;

        this.sendOnLoadingStarted();

        this.mRettificaGiacenzeRESTConsumer.loadListaFornitori(fornitori -> {
            this.sendOnFornitoriListLoaded(fornitori);

            this.sendOnLoadingEnded();

            this.requestLU();
        }, this::sendError);
    }

    public void requestLU() {
        this.sendOnLUOpenRequest((mtbColt, created) -> {
            this.mCurrentMtbColt = mtbColt;
            this.mIsCreatedLU = created;

            this.sendLUOpened(mtbColt);
        });
    }

    public RettificaGiacenzeViewModel setListener(RettificaGiacenzeViewModel.Listener listener) {
        this.mListener = listener;
        return this;
    }


    public void processBarcodeDTO(BarcodeScanDTO barcodeScanDTO, Runnable onComplete) {
        if (UtilityBarcode.isEtichetta128(barcodeScanDTO)) {
            //Cerco tramite etichetta ean 128 (che può indicarmi un articolo o una UL)
            this.executeEtichettaEan128(barcodeScanDTO, onComplete);

        } else if (UtilityBarcode.isEanPeso(barcodeScanDTO)) {
            //Cerco tramite articolo ean peso
            this.executeEtichettaEanPeso(barcodeScanDTO, onComplete);

        } else if (UtilityBarcode.isEtichettaArt(barcodeScanDTO)) {
            this.searchArtInt(barcodeScanDTO.getStringValue(), onComplete);

        } else {
            onComplete.run();
        }
    }

    private void executeEtichettaEan128(BarcodeScanDTO barcodeScanDTO, Runnable onComplete) {
        mBarcodeRESTConsumer.decodeEan128(barcodeScanDTO, ean128Model -> {

            String barcodeProd = null;
            String codMart = null;

            if (!UtilityString.isNullOrEmpty(ean128Model.Sscc)) barcodeProd = ean128Model.Sscc;
            if (!UtilityString.isNullOrEmpty(ean128Model.Gtin)) barcodeProd = ean128Model.Gtin;
            if (!UtilityString.isNullOrEmpty(ean128Model.Content))
                barcodeProd = ean128Model.Content;

            if (!UtilityString.isNullOrEmpty(ean128Model.Internal1))
                codMart = ean128Model.Internal1;


            if (!UtilityString.isNullOrEmpty(barcodeProd)) {

                PickDataDTO pickDataDTO = PickDataDTO.fromEan128(ean128Model);
                this.loadArticolo(barcodeProd, pickDataDTO, onComplete);
            } else if (!UtilityString.isNullOrEmpty(codMart)) {
                this.searchArtInt(codMart, onComplete);
            } else {
                //EAN 128 non completo o comunque mancano i riferimenti al prodotto
                onComplete.run();
            }
        }, this::sendError);
    }

    private void executeEtichettaEanPeso(BarcodeScanDTO barcodeScanDTO, Runnable onComplete) {
        try {
            Ean13PesoModel ean13PesoModel = Ean13PesoModel.fromBarcode(barcodeScanDTO.getStringValue());
            this.loadArticolo(ean13PesoModel.getPrecode(), PickDataDTO.fromEan128(ean13PesoModel.toEan128()), onComplete);
        } catch (Exception ex) {
            this.sendError(ex);
        }
    }

    private void loadArticolo(String barcodeProd, PickDataDTO pickData, Runnable onComplete) {
        this.mArticoloRESTConsumer.getByBarcodeProd(barcodeProd, mtbAartList -> {
            if (onComplete != null) onComplete.run();

            if (mtbAartList != null && mtbAartList.size() > 0) {
                this.dispatchArt(mtbAartList.get(0), pickData);
            } else {
                this.sendError(new NoResultFromBarcodeException(barcodeProd));
            }

        }, this::sendError);
    }

    public void searchArtFor(String codAlis, String queryText) {
        this.sendOnLoadingStarted();

        mRettificaGiacenzeRESTConsumer.searchArtForn(codAlis, queryText, listaArts -> {
            this.sendOnLoadingEnded();

            List<MtbAart> mtbAarts = Stream.of(listaArts).map(x -> (MtbAart) x).toList();
            dispatchArts(mtbAarts);
        }, this::sendError);
    }

    public void searchArtInt(String queryText, Runnable onComplete) {
        this.sendOnLoadingStarted();

        mRettificaGiacenzeRESTConsumer.searchArtInt(queryText, listaArts -> {
            this.sendOnLoadingEnded();

            dispatchArts(listaArts);

            if (onComplete != null) onComplete.run();
        }, this::sendError);
    }


    private void dispatchArts(List<MtbAart> artsList) {
        if (artsList == null || artsList.size() == 0) {
            this.sendError(new NoArtsFoundException());
            return;
        }

        RunnableArgs<MtbAart> dispatchArtRunnable = mtbAart -> {

            var matchRows = Stream.of(this.mCurrentMtbColt.getMtbColr())
                    .filter(x -> x.getCodMart().equalsIgnoreCase(mtbAart.getCodMart()))
                    .toList();

            if (matchRows.size() != 1) {
                dispatchArt(mtbAart, null);
            } else {
                dispatchRowEdit(matchRows.get(0));
            }

        };

        if (artsList.size() == 1) {
            dispatchArtRunnable.run(artsList.get(0));
        } else {
            this.sendOnArtListLoaded(new ArrayList<>(artsList), dispatchArtRunnable);
        }
    }


    public void dispatchArt(MtbAart mtbAart, PickDataDTO pickDataDTO) {
        PickingObjectDTO pickingObjectDTO = new PickingObjectDTO()
                .setMtbAart(mtbAart)
                .setTempPickData(pickDataDTO);

        BigDecimal numCnfDaPrelevare = null;
        BigDecimal qtaColDaPrelevare = null;
        BigDecimal qtaCnfDaPrelevare = null;

        BigDecimal initialNumCnf = null;
        BigDecimal initialQtaCnf = null;
        BigDecimal initialQtaTot = null;

        String partitaMag = null;
        Date dataScad = null;

        boolean canPartitaMagBeChanged = true;

        if (pickingObjectDTO.getTempPickData() != null && pickingObjectDTO.getTempPickData().getManualPickDTO() != null) {
            //Oppure le info del barcode scansionato
            PickDataDTO.ManualPickDTO manualPickDTO = pickingObjectDTO.getTempPickData().getManualPickDTO();

            qtaColDaPrelevare = manualPickDTO.getQtaTot();
            numCnfDaPrelevare = manualPickDTO.getNumCnf();

            if (mtbAart.isFlagQtaCnfFissaBoolean()) {
                qtaCnfDaPrelevare = mtbAart.getQtaCnf();

                if (manualPickDTO.isEanPeso()) {
                    if (mtbAart.getUntMisRifPeso() == MtbAart.UntMisRifPesoEnum.M) {
                        if (UtilityBigDecimal.equalsTo(mtbAart.getPesoKg(), BigDecimal.ZERO)) {
                            this.sendError(new InvalidPesoKGException());
                        } else {
                            qtaColDaPrelevare = UtilityBigDecimal.divide(qtaColDaPrelevare, mtbAart.getPesoKg());
                        }
                    }
                }
            } else if (qtaColDaPrelevare != null && numCnfDaPrelevare != null) {
                qtaCnfDaPrelevare = UtilityBigDecimal.divide(qtaColDaPrelevare, numCnfDaPrelevare);
            }


            if (qtaColDaPrelevare != null && numCnfDaPrelevare == null) {
                if (!mtbAart.isFlagQtaCnfFissaBoolean()) {
                    numCnfDaPrelevare = UtilityBigDecimal.divideAndRoundToInteger(qtaColDaPrelevare, mtbAart.getQtaCnf());
                    if (UtilityBigDecimal.equalsTo(numCnfDaPrelevare, BigDecimal.ZERO))
                        numCnfDaPrelevare = BigDecimal.ONE;
                    qtaCnfDaPrelevare = UtilityBigDecimal.divide(qtaColDaPrelevare, numCnfDaPrelevare);
                } else {
                    numCnfDaPrelevare = UtilityBigDecimal.divideToInteger(qtaColDaPrelevare, mtbAart.getQtaCnf());
                }
            } else if (numCnfDaPrelevare != null && qtaColDaPrelevare == null) {
                qtaCnfDaPrelevare = mtbAart.getQtaCnf();
                qtaColDaPrelevare = UtilityBigDecimal.multiply(numCnfDaPrelevare, qtaCnfDaPrelevare);
            }

            if (manualPickDTO.getMtbPartitaMag() != null) {
                partitaMag = manualPickDTO.getMtbPartitaMag().getPartitaMag();
                dataScad = manualPickDTO.getMtbPartitaMag().getDataScadD();
                canPartitaMagBeChanged = false;
            }
        } else {
            initialNumCnf = BigDecimal.ONE;
            initialQtaCnf = mtbAart.getQtaCnf();
            initialQtaTot = UtilityBigDecimal.multiply(initialNumCnf, initialQtaCnf);
        }

        if (numCnfDaPrelevare == null && qtaColDaPrelevare == null && initialNumCnf == null && initialQtaTot == null) {
            initialNumCnf = BigDecimal.ONE;
            initialQtaCnf = mtbAart.getQtaCnf();
            initialQtaTot = UtilityBigDecimal.multiply(initialNumCnf, initialQtaCnf);
        }

        if (dataScad == null && pickingObjectDTO.getMtbAart().getGgScadPartita() != null && pickingObjectDTO.getMtbAart().getGgScadPartita() > 0) {
            dataScad = UtilityDate.getDateInstance();
            Calendar c = new GregorianCalendar();
            c.setTime(dataScad);
            c.add(Calendar.DATE, pickingObjectDTO.getMtbAart().getGgScadPartita());
            dataScad = c.getTime();
        }

        this.sendOnItemDispatched(
                pickingObjectDTO,
                pickingObjectDTO.getMtbAart(),
                initialNumCnf,
                initialQtaCnf,
                initialQtaTot,
                mtbAart.getQtaEsistente(),
                mtbAart.getNumCnfEsistente(),
                mtbAart.getQtaImpegnata(),
                mtbAart.getNumCnfImpegnata(),
                qtaColDaPrelevare,
                numCnfDaPrelevare,
                qtaCnfDaPrelevare,
                partitaMag,
                dataScad,
                false,
                canPartitaMagBeChanged,
                true,
                (pickedQuantityDTO, shouldCloseLU) -> {
                    this.saveNewRow(pickingObjectDTO,
                            pickedQuantityDTO.getNumCnf(),
                            pickedQuantityDTO.getQtaCnf(),
                            pickedQuantityDTO.getQtaTot(),
                            pickedQuantityDTO.getPartitaMag(),
                            pickedQuantityDTO.getDataScad(),
                            shouldCloseLU);
                });
    }


    public void saveNewRow(PickingObjectDTO pickingObjectDTO, BigDecimal numCnf, BigDecimal qtaCnf, BigDecimal qtaTot, String partitaMag, Date dataScad, boolean shouldCloseLU) {
        this.sendOnLoadingStarted();

        final MtbColr mtbColr = new MtbColr()
                .setCodMart(pickingObjectDTO.getMtbAart().getCodMart())
                .setPartitaMag(partitaMag)
                .setDataScadPartita(dataScad)
                .setDescrizione(pickingObjectDTO.getMtbAart().getDescrizioneEstesa())
                .setDatetimeRow(UtilityDate.getDateInstance())
                .setCausale(MtbColr.Causale.RETTIFICA)
                .setUtente(mCurrentUser);

        mtbColr.setOperation(CommonModelConsts.OPERATION.INSERT_OR_UPDATE);

//        if (!mIsCreatedLU && mCurrentMtbColt.isDocumentPresent()) {
        mtbColr
                .setQtaCol(BigDecimal.ZERO)
                .setNumCnf(BigDecimal.ZERO)
                .setDataCollo(mCurrentMtbColt.getDataColloS())
                .setNumCollo(mCurrentMtbColt.getNumCollo())
                .setGestione(mCurrentMtbColt.getGestione())
                .setSerCollo(mCurrentMtbColt.getSerCollo());


        mColliMagazzinoRESTConsumer.creaRettificaCollo(mtbColr,
                numCnf,
                qtaTot,
                savedMtbColr -> {
                    mtbColr
                            .setQtaCol(savedMtbColr.getQtaCol())
                            .setQtaCnf(savedMtbColr.getQtaCnf())
                            .setNumCnf(savedMtbColr.getNumCnf())
                            .setUntMis(pickingObjectDTO.getMtbAart().getUntMis())
                            .setMtbAart(pickingObjectDTO.getMtbAart());

                    mCurrentMtbColt.getMtbColr().add(mtbColr);

                    this.mAnyEditDone = true;

                    this.sendOnRowSaved();
                    this.sendOnLoadingEnded();

                    if (shouldCloseLU) closeLU(true, null);
                }, this::sendError);
//        } else {
//            mtbColr
//                    .setQtaCol(qtaTot)
//                    .setQtaCnf(qtaCnf)
//                    .setNumCnf(numCnf);
//
//            MtbColt cloneMtbColt = (MtbColt) mCurrentMtbColt.clone();
//            cloneMtbColt.setOperation(CommonModelConsts.OPERATION.NO_OP);
//
//            cloneMtbColt.setMtbColr(new ObservableArrayList<>());
//
//            cloneMtbColt.getMtbColr().add(mtbColr);
//
//            mColliMagazzinoRESTConsumer.saveCollo(cloneMtbColt, value -> {
//                mtbColr
//                        .setDataCollo(value.getDataColloS())
//                        .setNumCollo(value.getNumCollo())
//                        .setGestione(value.getGestione())
//                        .setSerCollo(value.getSerCollo())
//                        .setRiga(value.getMtbColr().get(0).getRiga())
//                        .setUntMis(pickingObjectDTO.getMtbAart().getUntMis())
//                        .setMtbAart(pickingObjectDTO.getMtbAart());
//
//                mCurrentMtbColt.getMtbColr().add(mtbColr);
//
//                this.mAnyEditDone = true;
//
//                this.sendOnRowSaved();
//                this.sendOnLoadingEnded();
//
//                if (shouldCloseLU) closeLU(true, null);
//            }, this::sendError);
//        }
    }


    public void closeLU(boolean saveCausale) {
        closeLU(saveCausale, null);
    }

    public void closeLU(boolean saveCausale, Runnable onComplete) {
        if (mCurrentMtbColt == null) {
            if (onComplete != null) onComplete.run();
            return;
        }

        this.sendOnLoadingStarted();

        this.mColliMagazzinoRESTConsumer.canLUBeDeleted(mCurrentMtbColt, canBeDeleted -> {

            if (canBeDeleted) {
                deleteLU(() -> {
                    this.sendLUClosed();
                    this.sendOnLoadingEnded();
                });
            } else {

                Runnable saveAction = () -> {
                    this.mColliMagazzinoRESTConsumer.updateDataFine(
                            mCurrentMtbColt, () -> {
                                this.sendLUPositionChangeRequest((shouldChangePosition, mtbDepoPosizione) -> {

                                    if (shouldChangePosition) {
                                        this.savePosizione(mtbDepoPosizione, () -> {
                                            this.mAnyEditDone = false;
                                            postSaveBehaviour(onComplete);
                                        });
                                    } else {
                                        this.mAnyEditDone = false;
                                        postSaveBehaviour(onComplete);
                                    }

                                });
                            }, this::sendError);
                };

                if (saveCausale || mAnyEditDone) {
                    this.saveCausaleRettificaGiacenze(saveAction);
                } else {
                    saveAction.run();
                }

            }

        }, this::sendError);
    }


    private void saveCausaleRettificaGiacenze(Runnable onComplete) {
        this.mColliMagazzinoRESTConsumer.confirmGiacenzaUL(mCurrentMtbColt, onComplete, this::sendError);
    }

    private void savePosizione(MtbDepoPosizione mtbDepoPosizione, Runnable onComplete) {
        MtbColt cloneMtbColt = (MtbColt) mCurrentMtbColt.clone();
        cloneMtbColt.setOperation(CommonModelConsts.OPERATION.UPDATE);
        cloneMtbColt.setMtbColr(null);
        cloneMtbColt.setPosizione(mtbDepoPosizione != null ? mtbDepoPosizione.getPosizione() : CommonModelConsts.ENTITY_NULL_STRING);

        this.mColliMagazzinoRESTConsumer.saveCollo(cloneMtbColt, mtbColt -> onComplete.run(), this::sendError);
    }

    private void postSaveBehaviour(Runnable onComplete) {
        if (!mCurrentMtbColt.getDisablePrint()) {
            printLU(() -> {
                this.mCurrentMtbColt = null;
                this.sendLUClosed();
                this.sendOnLoadingEnded();
                if (onComplete != null) onComplete.run();
            });
        } else {
            this.mCurrentMtbColt = null;
            this.sendLUClosed();
            this.sendOnLoadingEnded();
            if (onComplete != null) onComplete.run();
        }
    }

    private void deleteLU(Runnable onComplete) {
        mColliMagazzinoRESTConsumer.deleteCollo(mCurrentMtbColt, () -> {
            this.mCurrentMtbColt = null;

            if (onComplete != null) onComplete.run();
        }, this::sendError);
    }

    private void printLU(Runnable onComplete) {
        this.sendLUPrintRequest(shouldPrint -> {
            if (!shouldPrint) {
                onComplete.run();
            } else {

                this.mPrinterRESTConsumer.printCollo(mCurrentMtbColt, () -> {
                    this.sendLUSuccessfullyPrinted();
                    onComplete.run();
                }, ex -> this.sendLUPrintError(ex, onComplete));
            }
        });
    }

    public void dispatchRowEdit(MtbColr mtbColrToUpdate) {

        this.mRettificaGiacenzeRESTConsumer.searchArtInt(mtbColrToUpdate.getMtbAart().getCodMart(), newMtbAartList -> {

            var newMtbAart = newMtbAartList.get(0);

            final PickingObjectDTO pickingObjectDTO = new PickingObjectDTO()
                    .setMtbAart(newMtbAart);

            this.sendOnItemDispatched(
                    pickingObjectDTO,
                    pickingObjectDTO.getMtbAart(),
                    mtbColrToUpdate.getNumCnf(),
                    mtbColrToUpdate.getQtaCnf(),
                    mtbColrToUpdate.getQtaCol(),
                    newMtbAart.getQtaEsistente(), newMtbAart.getNumCnfEsistente(),
                    newMtbAart.getQtaImpegnata(), newMtbAart.getNumCnfImpegnata(),
                    null,
                    null,
                    null,
                    mtbColrToUpdate.getPartitaMag(),
                    mtbColrToUpdate.getDataScadPartitaD(),
                    false,
                    false,
                    true,
                    (pickedQuantityDTO, shouldCloseLU) -> {

                        this.saveEditedRow(mtbColrToUpdate,
                                pickedQuantityDTO.getNumCnf(),
                                pickedQuantityDTO.getQtaCnf(),
                                pickedQuantityDTO.getQtaTot(),
                                pickedQuantityDTO.getPartitaMag(),
                                pickedQuantityDTO.getDataScad(),
                                shouldCloseLU);
                    });
        }, this::sendError);

    }

    private void saveEditedRow(MtbColr mtbColrToUpdate, BigDecimal numCnf, BigDecimal qtaCnf, BigDecimal qtaTot, String partitaMag, Date dataScad, boolean shouldCloseLU) {
        this.sendOnLoadingStarted();

//        if(!mIsCreatedLU && mCurrentMtbColt.isDocumentPresent()) {

        this.mColliMagazzinoRESTConsumer.creaRettificaCollo(
                mtbColrToUpdate,
                numCnf,
                qtaTot,
                savedMtbColr -> {
                    mtbColrToUpdate
                            .setQtaCol(qtaTot)
                            .setQtaCnf(qtaCnf)
                            .setNumCnf(numCnf)
                            .setOperation(CommonModelConsts.OPERATION.NO_OP);

                    this.mCurrentMtbColt.getMtbColr().remove(mtbColrToUpdate);
                    this.mCurrentMtbColt.getMtbColr().add(mtbColrToUpdate);

                    this.mAnyEditDone = true;

                    this.sendOnRowSaved();
                    this.sendOnLoadingEnded();
                },
                this::sendError
        );

//        } else {
//
//            MtbColt mtbColt = new MtbColt()
//                    .setNumCollo(mtbColrToUpdate.getNumCollo())
//                    .setDataCollo(mtbColrToUpdate.getDataColloS())
//                    .setSerCollo(mtbColrToUpdate.getSerCollo())
//                    .setGestione(mtbColrToUpdate.getGestione())
//                    .setMtbColr(new ObservableArrayList<>());
//            mtbColt.setOperation(CommonModelConsts.OPERATION.NO_OP);
//
//            final MtbColr mtbColr = (MtbColr) mtbColrToUpdate.clone();
//            mtbColr
//                    .setNumCnf(numCnf.subtract(mtbColr.getNumCnf()))
//                    .setQtaCnf(qtaCnf)
//                    .setQtaCol(qtaTot.subtract(mtbColr.getQtaCol()))
//                    .setPartitaMag(partitaMag)
//                    .setDataScadPartita(dataScad)
//                    .setUtente(SettingsManager.i().getUser().getFullname())
//                    .setCausale(MtbColr.Causale.RETTIFICA)
//                    .setDatetimeRow(UtilityDate.getDateInstance())
//                    .setOperation(CommonModelConsts.OPERATION.INSERT);
//
//            mtbColt.getMtbColr().add(mtbColr);
//
//            this.mColliMagazzinoRESTConsumer.saveCollo(mtbColt, (value) -> {
//
//                mtbColr.setNumCnf(numCnf)
//                        .setQtaCnf(qtaCnf)
//                        .setQtaCol(qtaTot);
//
//                this.mCurrentMtbColt.getMtbColr().remove(mtbColrToUpdate);
//                this.mCurrentMtbColt.getMtbColr().add(mtbColr);
//
//                this.mAnyEditDone = true;
//
//                this.sendOnRowSaved();
//                this.sendOnLoadingEnded();
//
//            }, this::sendError);
//        }
    }

    public void deleteRow(MtbColr mtbColrToDelete) {
        this.sendMtbColrDeleteRequest(shouldDelete -> {
            if (shouldDelete) {
                this.sendOnLoadingStarted();

//                if(!mIsCreatedLU && mCurrentMtbColt.isDocumentPresent()) {
                this.mColliMagazzinoRESTConsumer.creaRettificaCollo(
                        mtbColrToDelete,
                        BigDecimal.ZERO,
                        BigDecimal.ZERO,
                        savedMtbColr -> {
                            this.mCurrentMtbColt.getMtbColr().remove(mtbColrToDelete);
                            this.sendOnLoadingEnded();
                            this.sendOnRowSaved();
                        },
                        this::sendError
                );
//                } else {
//                    MtbColt mtbColt = new MtbColt()
//                            .setNumCollo(mtbColrToDelete.getNumCollo())
//                            .setDataCollo(mtbColrToDelete.getDataColloS())
//                            .setSerCollo(mtbColrToDelete.getSerCollo())
//                            .setGestione(mtbColrToDelete.getGestione())
//                            .setMtbColr(new ObservableArrayList<>());
//                    mtbColt.setOperation(CommonModelConsts.OPERATION.NO_OP);
//
//                    MtbColr mtbColr = (MtbColr) mtbColrToDelete.clone();
//                    mtbColr
//                            .setNumCnf(mtbColr.getNumCnf().multiply(new BigDecimal(-1)))
//                            .setQtaCnf(mtbColr.getQtaCnf())
//                            .setQtaCol(mtbColr.getQtaCol().multiply(new BigDecimal(-1)))
//                            .setPartitaMag(mtbColr.getPartitaMag())
//                            .setDataScadPartita(mtbColr.getDataScadPartitaD())
//                            .setUtente(SettingsManager.i().getUser().getFullname())
//                            .setCausale(MtbColr.Causale.RETTIFICA)
//                            .setDatetimeRow(UtilityDate.getDateInstance())
//                            .setOperation(CommonModelConsts.OPERATION.INSERT);
//
//                    mtbColt.getMtbColr().add(mtbColr);
//
//                    this.mColliMagazzinoRESTConsumer.saveCollo(mtbColt, (value) -> {
//                        this.mCurrentMtbColt.getMtbColr().remove(mtbColrToDelete);
//
//                        this.sendOnRowSaved();
//                        this.sendOnLoadingEnded();
//
//                    }, this::sendError);
//                }
            }
        });
    }

    private void sendOnLoadingStarted() {
        if (this.mListener != null) mListener.onLoadingStarted();
    }

    private void sendOnLoadingEnded() {
        if (this.mListener != null) mListener.onLoadingEnded();
    }

    private void sendOnFornitoriListLoaded(ArrayList<FornitoreDTO> fornitoriList) {
        if (this.mListener != null) mListener.onFornitoriLoaded(fornitoriList);
    }


    private void sendOnArtListLoaded(ArrayList<MtbAart> artList, RunnableArgs<MtbAart> onArtChoosed) {
        if (this.mListener != null) mListener.onArtListLoaded(artList, onArtChoosed);
    }

    private void sendOnLUOpenRequest(RunnableArgss<MtbColt, Boolean> onComplete) {
        if (this.mListener != null) mListener.onLUOpenRequest(onComplete);
    }

    private void sendError(Exception ex) {
        if (this.mListener != null) mListener.onError(ex);
    }

    private void sendLUOpened(MtbColt mtbColt) {
        if (this.mListener != null) mListener.onLUOpened(mtbColt);
    }

    private void sendLUClosed() {
        if (this.mListener != null) mListener.onLUClosed();
    }

    private void sendMtbColrDeleteRequest(RunnableArgs<Boolean> onComplete) {
        if (this.mListener != null) mListener.onMtbColrDeleteRequest(onComplete);
    }

    private void sendOnItemDispatched(PickingObjectDTO pickingObjectDTO,
                                      MtbAart mtbAart,
                                      BigDecimal initialNumCnf,
                                      BigDecimal initialQtaCnf,
                                      BigDecimal initialQtaTot,
                                      BigDecimal totalQtaInWarehouse,
                                      BigDecimal totalNumCnfInWarehouse,
                                      BigDecimal totalQtaCommitted,
                                      BigDecimal totalNumCnfCommitted,
                                      BigDecimal totalQtaToBeTaken,
                                      BigDecimal totalNumCnfToBeTaken,
                                      BigDecimal qtaCnfToBeTaken,
                                      String partitaMag,
                                      Date dataScad,
                                      boolean canOverflowOrderQuantity,
                                      boolean canPartitaMagBeChanged,
                                      boolean canLUBeClosed,
                                      RunnableArgss<PickedQuantityDTO, Boolean> onComplete) {
        if (this.mListener != null) mListener.onItemDispatched(pickingObjectDTO,
                mtbAart,
                initialNumCnf,
                initialQtaCnf,
                initialQtaTot,
                totalQtaInWarehouse,
                totalNumCnfInWarehouse,
                totalQtaCommitted,
                totalNumCnfCommitted,
                totalQtaToBeTaken,
                totalNumCnfToBeTaken,
                qtaCnfToBeTaken,
                partitaMag,
                dataScad,
                canOverflowOrderQuantity,
                canPartitaMagBeChanged,
                canLUBeClosed,
                onComplete);
    }

    private void sendOnRowSaved() {
        if (this.mListener != null) mListener.onRowSaved();
    }

    private void sendLUSuccessfullyPrinted() {
        if (this.mListener != null) mListener.onLUSuccessullyPrinted();
    }

    private void sendLUPrintRequest(RunnableArgs<Boolean> onComplete) {
        if (this.mListener != null) mListener.onLUPrintRequest(onComplete);
    }

    private void sendLUPrintError(Exception ex, Runnable onComplete) {
        if (this.mListener != null) mListener.onLUPrintError(ex, onComplete);
    }

    private void sendLUPositionChangeRequest(RunnableArgss<Boolean, MtbDepoPosizione> onComplete) {
        if (this.mListener != null) mListener.onLUPositionChangeRequest(onComplete);
    }

    public interface Listener extends ILUPrintListener, ILUPositionListener {
        void onLoadingStarted();

        void onLoadingEnded();

        void onFornitoriLoaded(ArrayList<FornitoreDTO> fornitoriList);

        void onArtListLoaded(ArrayList<MtbAart> artList, RunnableArgs<MtbAart> onArtChoosed);

        void onLUOpenRequest(RunnableArgss<MtbColt, Boolean> onComplete);

        void onLUOpened(MtbColt mtbColt);

        void onLUClosed();

        void onMtbColrDeleteRequest(RunnableArgs<Boolean> onComplete);

        void onError(Exception ex);

        void onItemDispatched(PickingObjectDTO pickingObjectDTO,
                              MtbAart mtbAart,
                              BigDecimal initialNumCnf,
                              BigDecimal initialQtaCnf,
                              BigDecimal initialQtaTot,
                              BigDecimal totalQtaInWarehouse,
                              BigDecimal totalNumCnfInWarehouse,
                              BigDecimal totalQtaCommitted,
                              BigDecimal totalNumCnfCommitted,
                              BigDecimal totalQtaToBeTaken,
                              BigDecimal totalNumCnfToBeTaken,
                              BigDecimal qtaCnfToBeTaken,
                              String partitaMag,
                              Date dataScad,
                              boolean canOverflowOrderQuantity,
                              boolean canPartitaMagBeChanged,
                              boolean canLUBeClosed,
                              RunnableArgss<PickedQuantityDTO, Boolean> onComplete);

        void onRowSaved();
    }

    public MtbColt getCurrentMtbColt() {
        return mCurrentMtbColt;
    }
}
