/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.ui.filters;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.internal.ui.util.SWTUtil;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.SelectionDialog;

public class CustomFiltersDialog extends SelectionDialog {

	private static final String SEPARATOR = ","; //$NON-NLS-1$

	private String fViewId;
	private boolean fEnablePatterns;
	private String[] fPatterns;
	private String[] fEnabledFilterIds;

	private FilterDescriptor[] fBuiltInFilters;

	private CheckboxTableViewer fCheckBoxList;
	private Button fEnableUserDefinedPatterns;
	private Text fUserDefinedPatterns;

	private Stack fFilterDescriptorChangeHistory;

	/**
	 * Creates a dialog to customize script element filters.
	 *
	 * @param shell
	 *            the parent shell
	 * @param viewId
	 *            the id of the view
	 * @param enablePatterns
	 *            <code>true</code> if pattern filters are enabled
	 * @param patterns
	 *            the filter patterns
	 * @param enabledFilterIds
	 *            the Ids of the enabled filters
	 */
	public CustomFiltersDialog(Shell shell, String viewId,
			boolean enablePatterns, String[] patterns,
			String[] enabledFilterIds) {

		super(shell);
		Assert.isNotNull(viewId);
		Assert.isNotNull(patterns);
		Assert.isNotNull(enabledFilterIds);

		fViewId = viewId;
		fPatterns = patterns;
		fEnablePatterns = enablePatterns;
		fEnabledFilterIds = enabledFilterIds;

		fBuiltInFilters = FilterDescriptor.getFilterDescriptors(fViewId);
		fFilterDescriptorChangeHistory = new Stack();
		setShellStyle(getShellStyle() | SWT.RESIZE);
	}

	@Override
	protected void configureShell(Shell shell) {
		setTitle(FilterMessages.CustomFiltersDialog_title);
		setMessage(FilterMessages.CustomFiltersDialog_filterList_label);
		super.configureShell(shell);
		// TODO: help system
		// PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
		// IDLTKHelpContextIds.CUSTOM_FILTERS_DIALOG);
	}

	/**
	 * Overrides method in Dialog
	 *
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite)
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		initializeDialogUnits(parent);
		// create a composite with standard margins and spacing
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginHeight = convertVerticalDLUsToPixels(
				IDialogConstants.VERTICAL_MARGIN);
		layout.marginWidth = convertHorizontalDLUsToPixels(
				IDialogConstants.HORIZONTAL_MARGIN);
		layout.verticalSpacing = convertVerticalDLUsToPixels(
				IDialogConstants.VERTICAL_SPACING);
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(
				IDialogConstants.HORIZONTAL_SPACING);
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		composite.setFont(parent.getFont());
		Composite group = composite;

		// Checkbox
		fEnableUserDefinedPatterns = new Button(group, SWT.CHECK);
		fEnableUserDefinedPatterns.setFocus();
		fEnableUserDefinedPatterns.setText(
				FilterMessages.CustomFiltersDialog_enableUserDefinedPattern);

		// Pattern field
		fUserDefinedPatterns = new Text(group, SWT.SINGLE | SWT.BORDER);
		GridData data = new GridData(
				GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
		data.widthHint = convertWidthInCharsToPixels(59);
		fUserDefinedPatterns.setLayoutData(data);
		String patterns = convertToString(fPatterns, SEPARATOR);
		fUserDefinedPatterns.setText(patterns);

		// Info text
		final Label info = new Label(group, SWT.LEFT);
		info.setText(FilterMessages.CustomFiltersDialog_patternInfo);

		// Enabling / disabling of pattern group
		fEnableUserDefinedPatterns.setSelection(fEnablePatterns);
		fUserDefinedPatterns.setEnabled(fEnablePatterns);
		info.setEnabled(fEnablePatterns);
		fEnableUserDefinedPatterns.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				boolean state = fEnableUserDefinedPatterns.getSelection();
				fUserDefinedPatterns.setEnabled(state);
				info.setEnabled(fEnableUserDefinedPatterns.getSelection());
				if (state)
					fUserDefinedPatterns.setFocus();
			}
		});

		// Filters provided by extension point
		if (fBuiltInFilters.length > 0)
			createCheckBoxList(group);

		applyDialogFont(parent);
		return parent;
	}

	private void createCheckBoxList(Composite parent) {
		// Filler
		new Label(parent, SWT.NONE);

		Label info = new Label(parent, SWT.LEFT);
		info.setText(FilterMessages.CustomFiltersDialog_filterList_label);

		fCheckBoxList = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.heightHint = fCheckBoxList.getTable().getItemHeight() * 10;
		fCheckBoxList.getTable().setLayoutData(data);

		fCheckBoxList.setLabelProvider(createLabelPrivder());
		fCheckBoxList.setContentProvider(new ArrayContentProvider());
		Arrays.sort(fBuiltInFilters);
		fCheckBoxList.setInput(fBuiltInFilters);
		setInitialSelections(getEnabledFilterDescriptors());

		List initialSelection = getInitialElementSelections();
		if (initialSelection != null && !initialSelection.isEmpty())
			checkInitialSelections();

		// Description
		info = new Label(parent, SWT.LEFT);
		info.setText(FilterMessages.CustomFiltersDialog_description_label);
		final Text description = new Text(parent, SWT.LEFT | SWT.WRAP
				| SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.V_SCROLL);
		data = new GridData(GridData.FILL_HORIZONTAL);
		data.heightHint = convertHeightInCharsToPixels(3);
		description.setLayoutData(data);
		fCheckBoxList.addSelectionChangedListener(event -> {
			ISelection selection = event.getSelection();
			if (selection instanceof IStructuredSelection) {
				Object selectedElement = ((IStructuredSelection) selection)
						.getFirstElement();
				if (selectedElement instanceof FilterDescriptor)
					description.setText(((FilterDescriptor) selectedElement)
							.getDescription());
			}
		});
		fCheckBoxList.addCheckStateListener(event -> {
			Object element = event.getElement();
			if (element instanceof FilterDescriptor) {
				// renew if already touched
				if (fFilterDescriptorChangeHistory.contains(element))
					fFilterDescriptorChangeHistory.remove(element);
				fFilterDescriptorChangeHistory.push(element);
			}
		});

		addSelectionButtons(parent);
	}

	private void addSelectionButtons(Composite composite) {
		Composite buttonComposite = new Composite(composite, SWT.RIGHT);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		buttonComposite.setLayout(layout);
		GridData data = new GridData(
				GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL);
		data.grabExcessHorizontalSpace = true;
		composite.setData(data);

		// Select All button
		String label = FilterMessages.CustomFiltersDialog_SelectAllButton_label;
		Button selectButton = createButton(buttonComposite,
				IDialogConstants.SELECT_ALL_ID, label, false);
		SWTUtil.setButtonDimensionHint(selectButton);
		SelectionListener listener = new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				fCheckBoxList.setAllChecked(true);
				fFilterDescriptorChangeHistory.clear();
				for (int i = 0; i < fBuiltInFilters.length; i++)
					fFilterDescriptorChangeHistory.push(fBuiltInFilters[i]);
			}
		};
		selectButton.addSelectionListener(listener);

		// De-select All button
		label = FilterMessages.CustomFiltersDialog_DeselectAllButton_label;
		Button deselectButton = createButton(buttonComposite,
				IDialogConstants.DESELECT_ALL_ID, label, false);
		SWTUtil.setButtonDimensionHint(deselectButton);
		listener = new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				fCheckBoxList.setAllChecked(false);
				fFilterDescriptorChangeHistory.clear();
				for (int i = 0; i < fBuiltInFilters.length; i++)
					fFilterDescriptorChangeHistory.push(fBuiltInFilters[i]);
			}
		};
		deselectButton.addSelectionListener(listener);
	}

	private void checkInitialSelections() {
		Iterator itemsToCheck = getInitialElementSelections().iterator();
		while (itemsToCheck.hasNext())
			fCheckBoxList.setChecked(itemsToCheck.next(), true);
	}

	@Override
	protected void okPressed() {
		if (fBuiltInFilters != null) {
			ArrayList result = new ArrayList();
			for (int i = 0; i < fBuiltInFilters.length; ++i) {
				if (fCheckBoxList.getChecked(fBuiltInFilters[i]))
					result.add(fBuiltInFilters[i]);
			}
			setResult(result);
		}
		super.okPressed();
	}

	private ILabelProvider createLabelPrivder() {
		return new LabelProvider() {
			@Override
			public Image getImage(Object element) {
				return null;
			}

			@Override
			public String getText(Object element) {
				if (element instanceof FilterDescriptor)
					return ((FilterDescriptor) element).getName();
				else
					return null;
			}
		};
	}

	// ---------- result handling ----------

	@Override
	protected void setResult(List newResult) {
		super.setResult(newResult);
		if (fUserDefinedPatterns.getText().length() > 0) {
			fEnablePatterns = fEnableUserDefinedPatterns.getSelection();
			fPatterns = convertFromString(fUserDefinedPatterns.getText(),
					SEPARATOR);
		} else {
			fEnablePatterns = false;
			fPatterns = new String[0];
		}
	}

	/**
	 * @return the patterns which have been entered by the user
	 */
	public String[] getUserDefinedPatterns() {
		return fPatterns;
	}

	/**
	 * @return the Ids of the enabled built-in filters
	 */
	public String[] getEnabledFilterIds() {
		Object[] result = getResult();
		Set<String> enabledIds = new HashSet<>(result.length);
		for (int i = 0; i < result.length; i++)
			enabledIds.add(((FilterDescriptor) result[i]).getId());
		return enabledIds.toArray(new String[enabledIds.size()]);
	}

	/**
	 * @return <code>true</code> if the user-defined patterns are disabled
	 */
	public boolean areUserDefinedPatternsEnabled() {
		return fEnablePatterns;
	}

	/**
	 * @return a stack with the filter descriptor check history
	 *
	 */
	public Stack getFilterDescriptorChangeHistory() {
		return fFilterDescriptorChangeHistory;
	}

	private FilterDescriptor[] getEnabledFilterDescriptors() {
		FilterDescriptor[] filterDescs = fBuiltInFilters;
		List<FilterDescriptor> result = new ArrayList<>(filterDescs.length);
		List<String> enabledFilterIds = Arrays.asList(fEnabledFilterIds);
		for (int i = 0; i < filterDescs.length; i++) {
			String id = filterDescs[i].getId();
			if (enabledFilterIds.contains(id))
				result.add(filterDescs[i]);
		}
		return result.toArray(new FilterDescriptor[result.size()]);
	}

	public static String[] convertFromString(String patterns,
			String separator) {
		StringTokenizer tokenizer = new StringTokenizer(patterns, separator,
				true);
		int tokenCount = tokenizer.countTokens();
		List<String> result = new ArrayList<>(tokenCount);
		boolean escape = false;
		boolean append = false;
		while (tokenizer.hasMoreTokens()) {
			String token = tokenizer.nextToken().trim();
			if (separator.equals(token)) {
				if (!escape)
					escape = true;
				else {
					addPattern(result, separator);
					append = true;
				}
			} else {
				if (!append)
					result.add(token);
				else
					addPattern(result, token);
				append = false;
				escape = false;
			}
		}
		return result.toArray(new String[result.size()]);
	}

	private static void addPattern(List<String> list, String pattern) {
		if (list.isEmpty())
			list.add(pattern);
		else {
			int index = list.size() - 1;
			list.set(index, (list.get(index)) + pattern);
		}
	}

	public static String convertToString(String[] patterns, String separator) {
		int length = patterns.length;
		StringBuffer strBuf = new StringBuffer();
		if (length > 0)
			strBuf.append(escapeSeparator(patterns[0], separator));
		else
			return ""; //$NON-NLS-1$
		int i = 1;
		while (i < length) {
			strBuf.append(separator);
			strBuf.append(" "); //$NON-NLS-1$
			strBuf.append(escapeSeparator(patterns[i++], separator));
		}
		return strBuf.toString();
	}

	private static String escapeSeparator(String pattern, String separator) {
		int length = pattern.length();
		StringBuffer buf = new StringBuffer(length);
		for (int i = 0; i < length; i++) {
			char ch = pattern.charAt(i);
			if (separator.equals(String.valueOf(ch)))
				buf.append(ch);
			buf.append(ch);
		}
		return buf.toString();

	}
}
