package it.integry.integrywmsnative.gest.ordini_uscita_elenco.dialogs;

import androidx.lifecycle.MutableLiveData;

import com.annimon.stream.Stream;
import com.annimon.stream.function.Predicate;

import java.util.Date;
import java.util.List;

import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.gest.ordini_uscita_elenco.OrdiniUscitaElencoDTO;

public class DialogVenditaFiltroAvanzatoViewModel {

    private Predicate<OrdiniUscitaElencoDTO> currentDepositoPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentIdViaggioPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentNumOrdsPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentClientePredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentDataConsPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentTermConsPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentVettorePredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentAgentePredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentAutomezzoPredicate = null;
    private Predicate<OrdiniUscitaElencoDTO> currentPaesePredicate = null;


    private List<OrdiniUscitaElencoDTO> initialOrderList;
    private final MutableLiveData<List<OrdiniUscitaElencoDTO>> currentFilteredOrderList = new MutableLiveData<>();

    public void init(List<OrdiniUscitaElencoDTO> initialList) {
        this.initialOrderList = initialList;
        this.currentFilteredOrderList.setValue(this.initialOrderList);
    }

    public MutableLiveData<List<OrdiniUscitaElencoDTO>> getMutableFilteredOrderList() {
        return this.currentFilteredOrderList;
    }

    public void setIDViaggioFilter(String idViaggio) {
        if(UtilityString.isNullOrEmpty(idViaggio)) currentIdViaggioPredicate = null;
        else {
            String[] idViaggiSplitted = idViaggio.split("[,\\ ]");

            try{
                List<Integer> idViaggiInteger = Stream.of(idViaggiSplitted)
                        .filter(x -> !UtilityString.isNullOrEmpty(x))
                        .map(Integer::parseInt).toList();

                currentIdViaggioPredicate = o -> idViaggiInteger.contains(o.getIdViaggio());
            } catch (NumberFormatException ex) {
                currentIdViaggioPredicate = null;
            }
        }
    }

    public void setDepositoFilter(String deposito) {
        if(UtilityString.isNullOrEmpty(deposito)) currentDepositoPredicate = null;
        else {
            currentDepositoPredicate = o -> o.getCodMdep().toLowerCase().equalsIgnoreCase(deposito);
        }
    }

    public void setNumOrdFilter(String numOrds) {
        if(UtilityString.isNullOrEmpty(numOrds)) currentNumOrdsPredicate = null;
        else {
            String[] numOrdsSplitted = numOrds.split("[,\\ ]");

            try{
                List<Integer> numOrdsInteger = Stream.of(numOrdsSplitted)
                        .filter(x -> !UtilityString.isNullOrEmpty(x))
                        .map(Integer::parseInt).toList();

                currentNumOrdsPredicate = o -> numOrdsInteger.contains(o.getNumOrd());
            } catch (NumberFormatException ex) {
                currentNumOrdsPredicate = null;
            }
        }
    }

    public void setClienteFilter(String cliente) {
        if(UtilityString.isNullOrEmpty(cliente)) currentClientePredicate = null;
        else {
            currentClientePredicate = o -> o.getRagSocOrd().toLowerCase().contains(cliente.toLowerCase());
        }
    }

    public void setTerminiConsegnaFilter(String terminiConsegna) {
        if(UtilityString.isNullOrEmpty(terminiConsegna)) currentTermConsPredicate = null;
        else {
            currentTermConsPredicate = o -> !UtilityString.isNullOrEmpty(o.getTermCons()) && o.getTermCons().equalsIgnoreCase(terminiConsegna);
        }
    }

    public void setVettoreFilter(String vettore) {
        if(UtilityString.isNullOrEmpty(vettore)) currentVettorePredicate = null;
        else {
            currentVettorePredicate = o -> (o.getCodVvet() + " - " + o.getDescrizioneVettore()).equalsIgnoreCase(vettore);
        }
    }

    public void setAutomezzoFilter(String automezzo) {
        if(UtilityString.isNullOrEmpty(automezzo)) currentAutomezzoPredicate = null;
        else {
            currentAutomezzoPredicate = o -> !UtilityString.isNullOrEmpty(o.getDescrizioneAuto()) && (o.getDescrizioneAuto().toLowerCase().contains(automezzo) || o.getDescrizioneAuto().equalsIgnoreCase(automezzo));
        }
    }

    public void setDataConsegnaFilter(Date dataConsegna) {
        if(dataConsegna == null) currentDataConsPredicate = null;
        else {
            currentDataConsPredicate = o -> o.getDataConsD().equals(dataConsegna);
        }
    }

    public void setAgenteFilter(String agente) {
        if(UtilityString.isNullOrEmpty(agente)) currentAgentePredicate = null;
        else {
            currentAgentePredicate = o -> !UtilityString.isNullOrEmpty(o.getNomeAgente()) && (o.getNomeAgente().toLowerCase().contains(agente) || o.getNomeAgente().equalsIgnoreCase(agente));
        }
    }

    public void setPaeseFilter(String paese) {
        if(UtilityString.isNullOrEmpty(paese)) currentPaesePredicate = null;
        else {
            currentPaesePredicate = o -> !UtilityString.isNullOrEmpty(o.getCitta()) && (o.getCitta().toLowerCase().contains(paese) || o.getCitta().equalsIgnoreCase(paese));
        }
    }

    public void applyAllTests() {

        List<OrdiniUscitaElencoDTO> returnList = null;

        if (currentNumOrdsPredicate == null &&
                currentClientePredicate == null &&
                currentDataConsPredicate == null &&
                currentTermConsPredicate == null &&
                currentVettorePredicate == null &&
                currentAutomezzoPredicate == null &&
                currentDepositoPredicate == null &&
                currentIdViaggioPredicate == null &&
                currentAgentePredicate == null &&
                currentPaesePredicate == null
        ) {
            returnList = this.initialOrderList;
        } else {
            Stream<OrdiniUscitaElencoDTO> tmpStream = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate == null || (currentNumOrdsPredicate.test(x))) &&
                                    (currentClientePredicate == null || (currentClientePredicate.test(x))) &&
                                    (currentDataConsPredicate == null || (currentDataConsPredicate.test(x))) &&
                                    (currentTermConsPredicate == null || (currentTermConsPredicate.test(x))) &&
                                    (currentVettorePredicate == null || (currentVettorePredicate.test(x))) &&
                                    (currentAutomezzoPredicate == null || (currentAutomezzoPredicate.test(x))) &&
                                    (currentDepositoPredicate == null || (currentDepositoPredicate.test(x))) &&
                                    (currentIdViaggioPredicate == null || (currentIdViaggioPredicate.test(x))) &&
                                    (currentAgentePredicate == null || (currentAgentePredicate.test(x))) &&
                                    (currentPaesePredicate == null || (currentPaesePredicate.test(x)))
                    );

            returnList = tmpStream.toList();
        }

        this.currentFilteredOrderList.setValue(returnList);
    }

}
