package org.joinmastodon.android.fragments.settings;

import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.InputType;
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.WindowInsets;
import android.widget.Button;
import android.widget.EditText;

import org.joinmastodon.android.R;
import org.joinmastodon.android.model.FilterKeyword;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.ActionModeHelper;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
import org.parceler.Parcels;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import me.grishka.appkit.utils.V;

public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword>{
	private Button fab;
	private ActionMode actionMode;
	private ArrayList<ListItem<FilterKeyword>> selectedItems=new ArrayList<>();
	private ArrayList<String> deletedItemIDs=new ArrayList<>();
	private MenuItem deleteItem;
	private Runnable actionModeDismisser=()->actionMode.finish();

	public FilterWordsFragment(){
		setListLayoutId(R.layout.recycler_fragment_with_text_fab);
	}

	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setTitle(R.string.settings_filter_muted_words);
		onDataLoaded(getArguments().getParcelableArrayList("words").stream().map(p->{
			FilterKeyword word=Parcels.unwrap(p);
			ListItem<FilterKeyword> item=new ListItem<>(word.keyword, null, null, word);
			item.isEnabled=true;
			item.setOnClick(this::onWordClick);
			return item;
		}).collect(Collectors.toList()));
		setHasOptionsMenu(true);
	}

	@Override
	protected void doLoadData(int offset, int count){}

	private void onWordClick(ListItem<FilterKeyword> item){
		showAlertForWord(item.parentObject);
	}

	private void onSelectionModeWordClick(CheckableListItem<FilterKeyword> item){
		if(selectedItems.remove(item)){
			item.checked=false;
		}else{
			item.checked=true;
			selectedItems.add(item);
		}
		rebindItem(item);
		updateActionModeTitle();
	}

	@Override
	public void onStop(){
		super.onStop();
		Bundle result=new Bundle();
		result.putParcelableArrayList("words", (ArrayList<? extends Parcelable>) data.stream().map(i->i.parentObject).map(Parcels::wrap).collect(Collectors.toCollection(ArrayList::new)));
		result.putStringArrayList("deleted", deletedItemIDs);
		setResult(true, result);
	}

	@Override
	public void onViewCreated(View view, Bundle savedInstanceState){
		super.onViewCreated(view, savedInstanceState);
		fab=view.findViewById(R.id.fab);
		fab.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_add_24px, 0, 0, 0);
		fab.setText(R.string.add_muted_word_short);
		fab.setOnClickListener(v->onFabClick());
	}

	@Override
	public void onApplyWindowInsets(WindowInsets insets){
		UiUtils.applyBottomInsetToFAB(fab, insets);
		super.onApplyWindowInsets(insets);
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
		inflater.inflate(R.menu.selectable_list, menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		enterSelectionMode(item.getItemId()==R.id.select_all);
		return true;
	}

	@Override
	public boolean wantsLightStatusBar(){
		if(actionMode!=null)
			return UiUtils.isDarkTheme();
		return super.wantsLightStatusBar();
	}

	private void onFabClick(){
		showAlertForWord(null);
	}

	private void showAlertForWord(FilterKeyword word){
		AlertDialog.Builder bldr=new M3AlertDialogBuilder(getActivity())
				.setHelpText(R.string.filter_add_word_help)
				.setTitle(word==null ? R.string.add_muted_word : R.string.edit_muted_word)
				.setNegativeButton(R.string.cancel, null);

		FloatingHintEditTextLayout editWrap=(FloatingHintEditTextLayout) bldr.getContext().getSystemService(LayoutInflater.class).inflate(R.layout.floating_hint_edit_text, null);
		EditText edit=editWrap.findViewById(R.id.edit);
		edit.setHint(R.string.filter_word_or_phrase);
		edit.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
		editWrap.updateHint();
		bldr.setView(editWrap)
				.setPositiveButton(word==null ? R.string.add : R.string.save, null);

		if(word!=null){
			edit.setText(word.keyword);
			bldr.setNeutralButton(R.string.delete, null);
		}
		AlertDialog alert=bldr.show();
		if(word!=null){
			Button deleteBtn=alert.getButton(AlertDialog.BUTTON_NEUTRAL);
			deleteBtn.setTextColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Error));
			deleteBtn.setOnClickListener(v->confirmDeleteWords(Collections.singletonList(word), alert::dismiss));
		}
		Button saveBtn=alert.getButton(AlertDialog.BUTTON_POSITIVE);
		saveBtn.setEnabled(false);
		saveBtn.setOnClickListener(v->{
			String input=edit.getText().toString();
			for(ListItem<FilterKeyword> item:data){
				if(item.parentObject.keyword.equalsIgnoreCase(input)){
					editWrap.setErrorState(getString(R.string.filter_word_already_in_list));
					return;
				}
			}
			if(word==null){
				FilterKeyword w=new FilterKeyword();
				w.wholeWord=true;
				w.keyword=input;
				ListItem<FilterKeyword> item=new ListItem<>(w.keyword, null, null, w);
				item.isEnabled=true;
				item.setOnClick(this::onWordClick);
				data.add(item);
				itemsAdapter.notifyItemInserted(data.size()-1);
			}else{
				word.keyword=input;
				word.wholeWord=true;
				for(ListItem<FilterKeyword> item:data){
					if(item.parentObject==word){
						rebindItem(item);
						break;
					}
				}
			}
			alert.dismiss();
		});
		edit.addTextChangedListener(new SimpleTextWatcher(e->saveBtn.setEnabled(e.length()>0)));
	}

	private void confirmDeleteWords(List<FilterKeyword> words, Runnable onConfirmed){
		AlertDialog alert=new M3AlertDialogBuilder(getActivity())
				.setTitle(words.size()==1 ? getString(R.string.settings_delete_filter_word, words.get(0).keyword) : getResources().getQuantityString(R.plurals.settings_delete_x_filter_words, words.size(), words.size()))
//				.setMessage(R.string.settings_delete_filter_confirmation)
				.setPositiveButton(R.string.delete, (dlg, item)->{
					if(onConfirmed!=null)
						onConfirmed.run();
					removeWords(words);
				})
				.setNegativeButton(R.string.cancel, null)
				.show();
		alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Error));
	}

	private void removeWords(List<FilterKeyword> words){
		ArrayList<Integer> indexes=new ArrayList<>();
		for(int i=0;i<data.size();i++){
			if(words.contains(data.get(i).parentObject)){
				indexes.add(0, i);
			}
		}
		for(int index:indexes){
			data.remove(index);
			itemsAdapter.notifyItemRemoved(index);
		}
		for(FilterKeyword w:words){
			if(w.id!=null)
				deletedItemIDs.add(w.id);
		}
	}

	private void enterSelectionMode(boolean selectAll){
		if(actionMode!=null)
			return;
		V.setVisibilityAnimated(fab, View.GONE);

		actionMode=ActionModeHelper.startActionMode(this, ()->elevationOnScrollListener.getCurrentStatusBarColor(), new ActionMode.Callback(){
			@Override
			public boolean onCreateActionMode(ActionMode mode, Menu menu){
				return true;
			}

			@Override
			public boolean onPrepareActionMode(ActionMode mode, Menu menu){
				mode.getMenuInflater().inflate(R.menu.settings_filter_words_action_mode, menu);
				deleteItem=menu.findItem(R.id.delete);
				return true;
			}

			@Override
			public boolean onActionItemClicked(ActionMode mode, MenuItem item){
				if(item.getItemId()==R.id.delete){
					confirmDeleteWords(selectedItems.stream().map(i->i.parentObject).collect(Collectors.toList()), ()->leaveSelectionMode(false));
				}
				return true;
			}

			@Override
			public void onDestroyActionMode(ActionMode mode){
				leaveSelectionMode(true);
			}
		});

		selectedItems.clear();
		for(int i=0;i<data.size();i++){
			ListItem<FilterKeyword> item=data.get(i);
			CheckableListItem<FilterKeyword> newItem=new CheckableListItem<>(item.title, null, CheckableListItem.Style.CHECKBOX, selectAll, null);
			newItem.isEnabled=true;
			newItem.setOnClick(this::onSelectionModeWordClick);
			newItem.parentObject=item.parentObject;
			if(selectAll)
				selectedItems.add(newItem);
			data.set(i, newItem);
		}
		itemsAdapter.notifyItemRangeChanged(0, data.size());
		updateActionModeTitle();
		addBackCallback(actionModeDismisser);
	}

	private void leaveSelectionMode(boolean fromActionMode){
		if(actionMode==null)
			return;
		ActionMode actionMode=this.actionMode;
		this.actionMode=null;
		if(!fromActionMode)
			actionMode.finish();
		V.setVisibilityAnimated(fab, View.VISIBLE);
		selectedItems.clear();

		for(int i=0;i<data.size();i++){
			ListItem<FilterKeyword> item=data.get(i);
			ListItem<FilterKeyword> newItem=new ListItem<>(item.title, null, null);
			newItem.isEnabled=true;
			newItem.setOnClick(this::onWordClick);
			newItem.parentObject=item.parentObject;
			data.set(i, newItem);
		}
		itemsAdapter.notifyItemRangeChanged(0, data.size());
		removeBackCallback(actionModeDismisser);
	}

	private void updateActionModeTitle(){
		actionMode.setTitle(getResources().getQuantityString(R.plurals.x_items_selected, selectedItems.size(), selectedItems.size()));
		deleteItem.setEnabled(!selectedItems.isEmpty());
	}
}
