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

import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.WindowManager;
import android.widget.ArrayAdapter;

import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;

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

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import it.integry.integrywmsnative.R;
import it.integry.integrywmsnative.core.di.BindableString;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.expansion.RunnableArgss;
import it.integry.integrywmsnative.core.model.GtbAnag;
import it.integry.integrywmsnative.core.rest.model.DocumentoResoDTO;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.databinding.DialogUltimeConsegneFiltroAvanzatoBinding;
import it.integry.integrywmsnative.databinding.DialogUltimiArriviFornitoreFiltroAvanzatoBinding;
import it.integry.integrywmsnative.gest.ultime_consegne_cliente.dialog.DialogUltimeConsegneFiltroAvanzato;

public class DialogUltimiArriviFornitoreFiltroAvanzato {

    private AlertDialog mAlert;
    private Context mContext;
    private DialogUltimiArriviFiltroAvanzatoViewModel mBaseViewModel;
    private RunnableArgs<DialogUltimiArriviFiltroAvanzatoViewModel> mOnDismiss;



    private ArrayAdapter<String> arrayAdapterRagSoc;

    private List<GtbAnag> mItems;
    private List<GtbAnag> mFilteredItems;

    private Predicate<GtbAnag> currentRagSocPredicate = null;
    private Predicate<GtbAnag> currentDataDocPredicate = null;

    public static AlertDialog make(final Context context,
                                   final List<GtbAnag> items,
                                   DialogUltimiArriviFiltroAvanzatoViewModel baseViewModel,
                                   RunnableArgs<DialogUltimiArriviFiltroAvanzatoViewModel> onDismiss) {
        return new DialogUltimiArriviFornitoreFiltroAvanzato(context, items, baseViewModel, onDismiss).mAlert;
    }

    public DialogUltimiArriviFornitoreFiltroAvanzato(final Context context,
                                              final List<GtbAnag> items,
                                              DialogUltimiArriviFiltroAvanzatoViewModel baseViewModel,
                                              RunnableArgs<DialogUltimiArriviFiltroAvanzatoViewModel> onDismiss) {
        mContext = context;
        mItems = items;
        mBaseViewModel = baseViewModel;
        mOnDismiss = onDismiss;

        DialogUltimiArriviFiltroAvanzatoViewModel viewModel = baseViewModel != null ? baseViewModel : new DialogUltimiArriviFiltroAvanzatoViewModel();

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        DialogUltimiArriviFornitoreFiltroAvanzatoBinding binding = DataBindingUtil.inflate(inflater, R.layout.dialog_ultimi_arrivi_fornitore_filtro_avanzato, null, false);

        final AlertDialog.Builder dialog = new AlertDialog.Builder(context)
                .setView(binding.getRoot());

        binding.setViewmodel(viewModel);
        initViewModelNew(viewModel);
        initView(binding, viewModel);

        mAlert = dialog.create();
        mAlert.setCanceledOnTouchOutside(false);

        mAlert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        mAlert.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        binding.positiveBtn.setOnClickListener(view -> {
            mAlert.dismiss();
        });

        binding.neutralBtn.setOnClickListener(view -> {
            resetAll(viewModel);
        });


        mAlert.setOnDismissListener(dialogInterface -> {
            if(mOnDismiss != null) mOnDismiss.run(viewModel);
        });

        refreshList();

    }

    private void resetAll(DialogUltimiArriviFiltroAvanzatoViewModel viewModel) {
        viewModel.ragSoc.set(null);
        viewModel.dataDoc.set(null);
    }

    private void initView(DialogUltimiArriviFornitoreFiltroAvanzatoBinding bindings, DialogUltimiArriviFiltroAvanzatoViewModel viewModel) {

        arrayAdapterRagSoc = new ArrayAdapter(mContext, R.layout.dialog_vendita_filtro_avanzato__single_item);
        arrayAdapterRagSoc.addAll(getAvailableRagSocs(false));
        bindings.filledExposedDropdownRagSoc.setAdapter(arrayAdapterRagSoc);

        bindings.filledExposedDropdownDataDoc.setOnClickListener(view -> {
            Calendar c = UtilityDate.getCalendarInstance();

            if(viewModel.dataDocDate != null) {
                c.setTime(viewModel.dataDocDate);
            }

            int mYear = c.get(Calendar.YEAR);
            int mMonth = c.get(Calendar.MONTH);
            int mDay = c.get(Calendar.DAY_OF_MONTH);

            DatePickerDialog datePickerDialog = new DatePickerDialog(mContext,
                    (view2, year, month, day) -> {

                        viewModel.dataDocDate = new GregorianCalendar(year, month, day).getTime();
                        viewModel.dataDoc.set(UtilityDate.formatDate(viewModel.dataDocDate, UtilityDate.COMMONS_DATE_FORMATS.DMY_HUMAN));

                    }, mYear, mMonth, mDay);
            datePickerDialog.show();
        });


        viewModel.ragSoc.refresh();
        viewModel.dataDoc.refresh();
    }

    private void initViewModelNew(DialogUltimiArriviFiltroAvanzatoViewModel viewModel) {

        BindableString.resetListeners(viewModel.ragSoc);
        BindableString.registerListener(viewModel.ragSoc, value -> {
            if (UtilityString.isNullOrEmpty(value)) currentRagSocPredicate = null;
            else {
                currentRagSocPredicate = o -> o.getRagSoc().equalsIgnoreCase(viewModel.ragSoc.get());
            }

            refreshList();
        });
    }

    private List<String> getAvailableRagSocs(boolean skipRecalc) {
        if(currentDataDocPredicate == null){
            mFilteredItems = mItems;
        } else if(!skipRecalc){
            Stream<GtbAnag> tmpStream = Stream.of(mItems)
                    .filter(x ->
                            (currentDataDocPredicate == null || (currentDataDocPredicate.test(x)))
                    );

            mFilteredItems = tmpStream.toList();
        }

        return Stream.of(mFilteredItems).map(x -> x.getCodAnag() + " - " + x.getRagSoc()).distinct().withoutNulls().toList();
    }


    private void refreshList() {

        if(currentRagSocPredicate == null && currentDataDocPredicate == null){
            mFilteredItems = mItems;
        } else {
            Stream<GtbAnag> tmpStream = Stream.of(mItems)
                    .filter(x ->
                            (currentRagSocPredicate == null || (currentRagSocPredicate.test(x))) &&
                                    (currentDataDocPredicate== null || (currentDataDocPredicate.test(x)))
                    );

            mFilteredItems = tmpStream.toList();
        }


    }



    public class DialogUltimiArriviFiltroAvanzatoViewModel {

        public BindableString ragSoc = new BindableString();
        public BindableString dataDoc = new BindableString();

        public Date dataDocDate;
    }

}
