package ch.threema.app.fragments;

import android.app.Activity;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.ListFragment;

import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.progressindicator.CircularProgressIndicator;

import java.util.ArrayList;
import java.util.HashSet;

import ch.threema.app.R;
import ch.threema.app.activities.GroupAddActivity;
import ch.threema.app.activities.MemberChooseActivity;
import ch.threema.app.activities.ProfilePicRecipientsActivity;
import ch.threema.app.adapters.FilterResultsListener;
import ch.threema.app.adapters.FilterableListAdapter;
import ch.threema.app.ui.EmptyView;
import ch.threema.app.ui.InsetSides;
import ch.threema.app.ui.SpacingValues;
import ch.threema.app.ui.ViewExtensionsKt;
import ch.threema.storage.models.ContactModel;

public abstract class MemberListFragment extends ListFragment implements FilterResultsListener {
    public static final String BUNDLE_ARG_PRESELECTED = "pres";
    public static final String BUNDLE_ARG_EXCLUDED = "excl";

    protected Activity activity;
    protected Parcelable listInstanceState;
    protected ExtendedFloatingActionButton floatingActionButton;
    protected ArrayList<String> preselectedIdentities = new ArrayList<>();
    protected ArrayList<String> excludedIdentities = new ArrayList<>();
    protected CircularProgressIndicator progressBar;
    protected View topLayout;
    protected FilterableListAdapter adapter;
    private SelectionListener selectionListener;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        activity = getActivity();
        selectionListener = (MemberChooseActivity) activity;

        Bundle bundle = getArguments();
        if (bundle != null) {
            preselectedIdentities = bundle.getStringArrayList(BUNDLE_ARG_PRESELECTED);
            excludedIdentities = bundle.getStringArrayList(BUNDLE_ARG_EXCLUDED);
        }

        topLayout = inflater.inflate(R.layout.fragment_list, container, false);
        return topLayout;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ArrayList<Integer> checkedItemPositions = null;

        // recover after rotation
        if (savedInstanceState != null) {
            this.listInstanceState = savedInstanceState.getParcelable(getBundleName());
            checkedItemPositions = savedInstanceState.getIntegerArrayList(getBundleName() + "c");
        }

        createListAdapter(
            checkedItemPositions,
            preselectedIdentities,
            excludedIdentities,
            activity instanceof GroupAddActivity,
            activity instanceof ProfilePicRecipientsActivity
        );
        preselectedIdentities = null;
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        getListView().setDividerHeight(0);
        getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        getListView().setClipToPadding(false);

        ViewExtensionsKt.applyDeviceInsetsAsPadding(
            getListView(),
            new InsetSides(false, true, true, true),
            SpacingValues.bottom(R.dimen.grid_unit_x10)
        );

        progressBar = view.findViewById(R.id.progress);

        floatingActionButton = view.findViewById(R.id.floating);
        floatingActionButton.hide();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        try {
            ListView listView = getListView();

            if (listView != null) {
                outState.putParcelable(getBundleName(), listView.onSaveInstanceState());
                // save checked items, if any
                if (listView.getChoiceMode() == AbsListView.CHOICE_MODE_MULTIPLE && getAdapter().getCheckedItemCount() > 0) {
                    outState.putIntegerArrayList(getBundleName() + "c", getAdapter().getCheckedItemPositions());
                }
            }
        } catch (Exception e) {
            // getListView may cause IllegalStateException
        }

        super.onSaveInstanceState(outState);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        selectionListener.onSelectionChanged();
    }


    protected void onAdapterCreated() {
        selectionListener.onSelectionChanged();
    }

    public HashSet<ContactModel> getSelectedContacts() {
        if (getAdapter() != null) {
            return (HashSet<ContactModel>) getAdapter().getCheckedItems();
        }
        return new HashSet<>();
    }

    public FilterableListAdapter getAdapter() {
        return adapter;
    }

    void setListAdapter(FilterableListAdapter adapter) {
        super.setListAdapter(adapter);

        if (isAdded()) {
            try {
                progressBar.setVisibility(View.GONE);

                // add text view if contact list is empty
                EmptyView emptyView = new EmptyView(activity);
                emptyView.setup(getEmptyText());
                ((ViewGroup) getListView().getParent()).addView(emptyView);
                getListView().setEmptyView(emptyView);
            } catch (IllegalStateException ignored) {
            }
        }
    }

    @Override
    public void onResultsAvailable(int count) {
        if (isAdded() && activity != null) {
            ((MemberChooseActivity) activity).onQueryResultChanged(this, count);
        }
    }

    public interface SelectionListener {
        void onSelectionChanged();
    }

    protected abstract void createListAdapter(
        @Nullable ArrayList<Integer> checkedItemPositions,
        @Nullable ArrayList<String> preselectedIdentities,
        @Nullable ArrayList<String> excludedIdentities,
        boolean group,
        boolean profilePics
    );

    protected abstract String getBundleName();

    protected abstract @StringRes int getEmptyText();
}
