package org.adaway.ui.lists.type;

import android.graphics.Color;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;
import androidx.paging.PagingData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import org.adaway.R;
import org.adaway.db.entity.HostListItem;
import org.adaway.ui.lists.ListsViewCallback;
import org.adaway.ui.lists.ListsViewModel;
import org.adaway.util.Clipboard;

/**
 * This class is a {@link Fragment} to display and manage lists of {@link org.adaway.ui.lists.ListsActivity}.
 *
 * @author Bruce BUJON (bruce.bujon(at)gmail(dot)com)
 */
public abstract class AbstractListFragment extends Fragment implements ListsViewCallback {
    /**
     * The view model (<code>null</code> if view is not created).
     */
    protected ListsViewModel mViewModel;
    /**
     * The current activity (<code>null</code> if view is not created).
     */
    protected FragmentActivity mActivity;
    /**
     * The current action mode when item is selection (<code>null</code> if no action started).
     */
    private ActionMode mActionMode;
    /**
     * The action mode callback (<code>null</code> if view is not created).
     */
    private ActionMode.Callback mActionCallback;
    /**
     * The hosts list related to the current action (<code>null</code> if view is not created).
     */
    private HostListItem mActionItem;
    /**
     * The view related hosts source of the current action (<code>null</code> if view is not created).
     */
    private View mActionSourceView;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // Store activity
        this.mActivity = requireActivity();
        // Create fragment view
        View view = inflater.inflate(R.layout.hosts_lists_fragment, container, false);
        /*
         * Configure recycler view.
         */
        // Store recycler view
        RecyclerView recyclerView = view.findViewById(R.id.hosts_lists_list);
        recyclerView.setHasFixedSize(true);
        // Defile recycler layout
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this.mActivity);
        recyclerView.setLayoutManager(linearLayoutManager);
        // Create recycler adapter
        ListsAdapter adapter = new ListsAdapter(this, isTwoRowsItem());
        recyclerView.setAdapter(adapter);
        /*
         * Create action mode.
         */
        // Create action mode callback to display edit/delete menu
        this.mActionCallback = new ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                // Get menu inflater
                MenuInflater inflater = actionMode.getMenuInflater();
                // Set action mode title
                actionMode.setTitle(R.string.checkbox_list_context_title);
                // Inflate edit/delete menu
                inflater.inflate(R.menu.checkbox_list_context, menu);
                // Return action created
                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                // Nothing special to do
                return false;
            }

            @Override
            public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
                // Check action item
                if (mActionItem == null) {
                    return false;
                }
                // Check item identifier
                if (item.getItemId() == R.id.edit_action) {
                    // Edit action item
                    editItem(mActionItem);
                    // Finish action mode
                    mActionMode.finish();
                    return true;
                } else if (item.getItemId() == R.id.delete_action) {
                    // Delete action item
                    deleteItem(mActionItem);
                    // Finish action mode
                    mActionMode.finish();
                    return true;
                } else {
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(ActionMode actionMode) {
                // Clear view background color
                if (mActionSourceView != null) {
                    mActionSourceView.setBackgroundColor(Color.TRANSPARENT);
                }
                // Clear current source and its view
                mActionItem = null;
                mActionSourceView = null;
                // Clear action mode
                mActionMode = null;
            }
        };
        /*
         * Load data.
         */
        // Get view model and bind it to the list view
        this.mViewModel = new ViewModelProvider(this.mActivity).get(ListsViewModel.class);
        getData().observe(getViewLifecycleOwner(), data -> adapter.submitData(getLifecycle(), data));
        // Return created view
        return view;
    }

    @Override
    public boolean startAction(HostListItem item, View sourceView) {
        // Check if there is already a current action
        if (this.mActionMode != null) {
            return false;
        }
        // Store current source and its view
        this.mActionItem = item;
        this.mActionSourceView = sourceView;
        // Get current item background color
        int currentItemBackgroundColor = getResources().getColor(R.color.selected_background, null);
        // Apply background color to view
        this.mActionSourceView.setBackgroundColor(currentItemBackgroundColor);
        // Start action mode and store it
        this.mActionMode = this.mActivity.startActionMode(this.mActionCallback);
        // Return event consumed
        return true;
    }

    @Override
    public boolean copyHostToClipboard(HostListItem item) {
        Clipboard.copyHostToClipboard(this.mActivity, item.getHost());
        return true;
    }

    /**
     * Ensure action mode is cancelled.
     */
    public void ensureActionModeCanceled() {
        if (this.mActionMode != null) {
            this.mActionMode.finish();
        }
    }

    protected abstract LiveData<PagingData<HostListItem>> getData();

    protected boolean isTwoRowsItem() {
        return false;
    }

    /**
     * Display a UI to add an item to the list.
     */
    public abstract void addItem();

    protected abstract void editItem(HostListItem item);

    protected void deleteItem(HostListItem item) {
        this.mViewModel.removeListItem(item);
    }

    @Override
    public void toggleItemEnabled(HostListItem item) {
        this.mViewModel.toggleItemEnabled(item);
    }
}
