/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *
 * Contributors:
 *     xored software, Inc. - initial API and Implementation
 *******************************************************************************/
package org.eclipse.dltk.validators.internal.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.internal.ui.util.SWTUtil;
import org.eclipse.dltk.internal.ui.util.TableLayoutComposite;
import org.eclipse.dltk.ui.util.PixelConverter;
import org.eclipse.dltk.validators.core.IValidator;
import org.eclipse.dltk.validators.core.IValidatorType;
import org.eclipse.dltk.validators.core.ValidatorRuntime;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
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.Table;
import org.eclipse.swt.widgets.TableColumn;

/**
 * A composite that displays installed InterpreterEnvironment's in a table.
 * InterpreterEnvironments can be added, removed, edited, and searched for.
 * <p>
 * This block implements ISelectionProvider - it sends selection change events
 * when the checked InterpreterEnvironment in the table changes, or when the
 * "use default" button check state changes.
 * </p>
 */
public class ValidatorBlock implements IAddValidatorDialogRequestor {

	/**
	 * This block's control
	 */
	private Composite fControl;

	/**
	 * Validators being displayed
	 */
	protected List<IValidator> fValidators = new ArrayList<>();

	/**
	 * The main list control
	 */
	protected CheckboxTableViewer fValidatorList;

	// Action buttons
	private Button fAddButton;
	private Button fRemoveButton;
	private Button fEditButton;
	private Button fCopyButton;

	// index of column used for sorting
	private int fSortColumn = 0;

	private Table fTable;

	/**
	 * Content provider to show a list of InterpreterEnvironments
	 */
	private static class ValidatorContentProvider
			implements IStructuredContentProvider {
		@Override
		public Object[] getElements(Object input) {
			return ((List) input).toArray();
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput,
				Object newInput) {
		}

		@Override
		public void dispose() {
		}
	}

	/**
	 * Label provider for installed InterpreterEnvironments table.
	 */
	private static class ValidatorLabelProvider extends LabelProvider
			implements ITableLabelProvider {

		/**
		 * @see ITableLabelProvider#getColumnText(Object, int)
		 */
		@Override
		public String getColumnText(Object element, int columnIndex) {
			if (element instanceof IValidator) {
				IValidator validator = (IValidator) element;
				switch (columnIndex) {
				case 0:
					return validator.getName();
				case 1:
					return validator.getValidatorType().getName();
				case 2:
					String nature = validator.getValidatorType().getNature();
					if (ValidatorRuntime.ANY_NATURE.equals(nature)) {
						return ValidatorMessages.ValidatorBlock_all;
					}
					IDLTKLanguageToolkit languageToolkit = DLTKLanguageManager
							.getLanguageToolkit(nature);
					if (languageToolkit != null) {
						return languageToolkit.getLanguageName();
					}
					return ValidatorMessages.ValidatorBlock_unknown;
				}
			}
			return element.toString();
		}

		/**
		 * @see ITableLabelProvider#getColumnImage(Object, int)
		 */
		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			if (columnIndex == 0) {
				// TODO: insert validator logo here
			}
			return null;
		}

	}

	/**
	 * Creates this block's control in the given control.
	 *
	 * @param ancestor
	 *                            containing control
	 * @param useManageButton
	 *                            whether to present a single 'manage...' button
	 *                            to the user that opens the installed
	 *                            InterpreterEnvironments pref page for
	 *                            InterpreterEnvironment management, or to
	 *                            provide 'add, remove, edit, and search'
	 *                            buttons.
	 */
	public void createControl(Composite ancestor) {

		Composite parent = new Composite(ancestor, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginHeight = 0;
		layout.marginWidth = 0;

		Font font = ancestor.getFont();
		parent.setFont(font);
		parent.setLayout(layout);

		fControl = parent;

		GridData data;

		Label tableLabel = new Label(parent, SWT.NONE);
		tableLabel.setText(ValidatorMessages.InstalledValidatorBlock_15);
		data = new GridData();
		data.horizontalSpan = 2;
		tableLabel.setLayoutData(data);
		tableLabel.setFont(font);

		PixelConverter conv = new PixelConverter(parent);
		data = new GridData(GridData.FILL_BOTH);
		data.widthHint = conv.convertWidthInCharsToPixels(50);
		TableLayoutComposite tblComposite = new TableLayoutComposite(parent,
				SWT.NONE);
		tblComposite.setLayoutData(data);
		fTable = new Table(tblComposite,
				SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);

		data = new GridData(GridData.FILL_BOTH);
		data.widthHint = 450;
		fTable.setLayoutData(data);
		fTable.setFont(font);

		fTable.setHeaderVisible(true);
		fTable.setLinesVisible(true);

		TableColumn column1 = new TableColumn(fTable, SWT.NULL);
		column1.setText(ValidatorMessages.InstalledValidatorBlock_0);
		column1.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				sortByName();
			}
		});

		TableColumn column2 = new TableColumn(fTable, SWT.NULL);
		column2.setText(ValidatorMessages.InstalledValidatorBlock_2);
		column2.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				sortByType();
			}
		});

		TableColumn column3 = new TableColumn(fTable, SWT.NULL);
		column3.setText(ValidatorMessages.InstalledValidatorBlock_1);
		// column3.addSelectionListener(new SelectionAdapter() {
		// public void widgetSelected(SelectionEvent e) {
		// sortByLocation();
		// }
		// });

		fValidatorList = new CheckboxTableViewer(fTable);
		fValidatorList.setLabelProvider(new ValidatorLabelProvider());
		fValidatorList.setContentProvider(new ValidatorContentProvider());
		fValidatorList.addCheckStateListener(event -> {
			IValidator validator = (IValidator) event.getElement();
			validator.setAutomatic(event.getChecked());
		});

		// by default, sort by name
		sortByName();

		fValidatorList.addSelectionChangedListener(evt -> enableButtons());

		fValidatorList.addDoubleClickListener(e -> {
			if (!fValidatorList.getSelection().isEmpty()) {
				editValidator();
			}
		});
		fTable.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent event) {
				if (event.character == SWT.DEL && event.stateMask == 0) {
					if (fRemoveButton.getEnabled())
						removeValidator();
				}
			}
		});

		Composite buttons = new Composite(parent, SWT.NULL);
		buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
		layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		buttons.setLayout(layout);
		buttons.setFont(font);

		fAddButton = createPushButton(buttons,
				ValidatorMessages.InstalledValidatorBlock_3);
		fAddButton.addListener(SWT.Selection, evt -> addValidator());

		fEditButton = createPushButton(buttons,
				ValidatorMessages.InstalledValidatorBlock_4);
		fEditButton.addListener(SWT.Selection, evt -> editValidator());

		fCopyButton = createPushButton(buttons,
				ValidatorMessages.InstalledValidatorBlock_16);
		fCopyButton.addListener(SWT.Selection, evt -> copyValidator());

		fRemoveButton = createPushButton(buttons,
				ValidatorMessages.InstalledValidatorBlock_5);
		fRemoveButton.addListener(SWT.Selection, evt -> removeValidator());

		// copied from ListDialogField.CreateSeparator()
		Label separator = new Label(buttons, SWT.NONE);
		separator.setVisible(false);
		GridData gd = new GridData();
		gd.horizontalAlignment = GridData.FILL;
		gd.verticalAlignment = GridData.BEGINNING;
		gd.heightHint = 4;
		separator.setLayoutData(gd);

		fillWithWorkspaceValidators();
		enableButtons();
	}

	/**
	 * Sorts by Interpreter type, and name within type.
	 */
	private void sortByType() {
		fValidatorList.setComparator(new ViewerComparator() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				if ((e1 instanceof IValidator) && (e2 instanceof IValidator)) {
					IValidator left = (IValidator) e1;
					IValidator right = (IValidator) e2;
					String leftType = left.getValidatorType().getName();
					String rightType = right.getValidatorType().getName();
					int res = leftType.compareToIgnoreCase(rightType);
					if (res != 0) {
						return res;
					}
					return left.getName().compareToIgnoreCase(right.getName());
				}
				return super.compare(viewer, e1, e2);
			}

			@Override
			public boolean isSorterProperty(Object element, String property) {
				return true;
			}
		});
		fSortColumn = 3;
	}

	/**
	 * Sorts by Interpreter name.
	 */
	private void sortByName() {
		fValidatorList.setComparator(new ViewerComparator() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				if ((e1 instanceof IValidator) && (e2 instanceof IValidator)) {
					IValidator left = (IValidator) e1;
					IValidator right = (IValidator) e2;
					String name = left.getName();
					if (name == null) {
						return 0;
					}
					return name.compareToIgnoreCase(right.getName());
				}
				return super.compare(viewer, e1, e2);
			}

			@Override
			public boolean isSorterProperty(Object element, String property) {
				return true;
			}
		});
		fSortColumn = 1;
	}

	private void enableButtons() {
		IStructuredSelection selection = fValidatorList
				.getStructuredSelection();
		int selectionCount = selection.size();

		boolean addEnabled = ValidatorRuntime
				.getPossibleValidatorTypes().length > 0;
		boolean editEnabled = selectionCount == 1;
		boolean removeEnabled = true;
		boolean copyEnabled = false && selectionCount > 0;// not implemented

		if (selectionCount > 0) {
			Iterator<?> iterator = selection.iterator();
			while (iterator.hasNext()) {
				IValidator install = (IValidator) iterator.next();
				if (isContributed(install)) {
					removeEnabled = false;
					copyEnabled = false;
				}
			}
		} else {
			removeEnabled = false;
		}
		fAddButton.setEnabled(addEnabled);
		fEditButton.setEnabled(editEnabled);
		fRemoveButton.setEnabled(removeEnabled);
		fCopyButton.setEnabled(copyEnabled);
	}

	protected Button createPushButton(Composite parent, String label) {
		return SWTUtil.createPushButton(parent, label, null);
	}

	private boolean isContributed(IValidator install) {
		return install.getValidatorType().isBuiltin();
	}

	/**
	 * Returns this block's control
	 *
	 * @return control
	 */
	public Control getControl() {
		return fControl;
	}

	/**
	 * Sets the InterpreterEnvironments to be displayed in this block
	 *
	 * @param validators
	 *                       InterpreterEnvironments to be displayed
	 */
	protected void setValidators(IValidator[] validators) {
		fValidators.clear();
		List<IValidator> automatic = new ArrayList<>();
		for (int i = 0; i < validators.length; i++) {
			if (validators[i].isAutomatic()) {
				automatic.add(validators[i]);
			}
			fValidators.add(validators[i]);
		}
		fValidatorList.setInput(fValidators);
		fValidatorList.setCheckedElements(automatic.toArray());
		fValidatorList.refresh();
	}

	/**
	 * Returns the InterpreterEnvironments currently being displayed in this
	 * block
	 *
	 * @return InterpreterEnvironments currently being displayed in this block
	 */
	public IValidator[] getValidators() {
		return fValidators.toArray(new IValidator[fValidators.size()]);
	}

	/**
	 * @see IAddValidatorDialogRequestor#isDuplicateName(String)
	 */
	@Override
	public boolean isDuplicateName(String name) {
		for (int i = 0; i < fValidators.size(); i++) {
			IValidator validator = fValidators.get(i);
			String validatorName = validator.getName();
			if (validatorName == null) {
				return true;
			}
			if (validatorName.equals(name)) {
				return true;
			}
		}
		return false;
	}

	private void removeValidator() {
		IStructuredSelection selection = fValidatorList
				.getStructuredSelection();
		IValidator[] validators = new IValidator[selection.size()];
		int i = 0;
		for (Iterator<?> iter = selection.iterator(); iter.hasNext();) {
			validators[i++] = (IValidator) iter.next();
		}
		removeValidators(validators);
	}

	/**
	 * Removes the given {@link IValidator}s from the table.
	 *
	 * @param validators
	 */
	public void removeValidators(IValidator[] validators) {
		for (int i = 0; i < validators.length; i++) {
			fValidators.remove(validators[i]);
		}
		fValidatorList.refresh();
	}

	protected Shell getShell() {
		return getControl().getShell();
	}

	/**
	 * Persist table settings into the give dialog store, prefixed with the
	 * given key.
	 *
	 * @param settings
	 *                      dialog store
	 * @param qualifier
	 *                      key qualifier
	 */
	public void saveColumnSettings(IDialogSettings settings, String qualifier) {
		int columnCount = fTable.getColumnCount();
		for (int i = 0; i < columnCount; i++) {
			settings.put(qualifier + ".columnWidth" + i, //$NON-NLS-1$
					fTable.getColumn(i).getWidth());
		}
		settings.put(qualifier + ".sortColumn", fSortColumn); //$NON-NLS-1$
	}

	/**
	 * Restore table settings from the given dialog store using the given key.
	 *
	 * @param settings
	 *                      dialog settings store
	 * @param qualifier
	 *                      key to restore settings from
	 */
	public void restoreColumnSettings(IDialogSettings settings,
			String qualifier) {
		fValidatorList.getTable().layout(true);
		restoreColumnWidths(settings, qualifier);
		try {
			fSortColumn = settings.getInt(qualifier + ".sortColumn"); //$NON-NLS-1$
		} catch (NumberFormatException e) {
			fSortColumn = 1;
		}
		switch (fSortColumn) {
		case 1:
			sortByName();
			break;
		case 2:
			// sortByLocation();
			break;
		case 3:
			sortByType();
			break;
		}
	}

	private void restoreColumnWidths(IDialogSettings settings,
			String qualifier) {
		int columnCount = fTable.getColumnCount();
		for (int i = 0; i < columnCount; i++) {
			int width = -1;

			try {
				width = settings.getInt(qualifier + ".columnWidth" + i); //$NON-NLS-1$
			} catch (NumberFormatException e) {
			}

			if (width <= 0) {
				fTable.getColumn(i).pack();
			} else {
				fTable.getColumn(i).setWidth(width);
			}
		}
	}

	/**
	 * Populates the InterpreterEnvironment table with existing
	 * InterpreterEnvironments defined in the workspace.
	 */
	protected void fillWithWorkspaceValidators() {
		List<IValidator> all = new ArrayList<>();
		IValidatorType[] types = ValidatorRuntime.getValidatorTypes();
		for (int i = 0; i < types.length; i++) {
			final IValidatorType type = types[i];
			if (type.isBuiltin() && !type.isConfigurable())
				continue;
			IValidator[] validators = type.getValidators();
			if (validators != null) {
				for (int j = 0; j < validators.length; j++) {
					all.add(validators[j].getWorkingCopy());
				}
			}
		}
		setValidators(all.toArray(new IValidator[all.size()]));
	}

	@Override
	public void validatorAdded(IValidator validator) {
		fValidators.add(validator);
		fValidatorList.add(validator);
		fValidatorList.setChecked(validator, validator.isAutomatic());
		fValidatorList.setSelection(new StructuredSelection(validator));
	}

	// Make sure that Validatortandin ids are unique if multiple calls to
	// System.currentTimeMillis()
	// happen very quickly
	private static String fgLastUsedID;

	/**
	 * Find a unique Interpreter id. Check existing 'real' Validator, as well as
	 * the last id used for a Validatortandin.
	 */
	protected String createUniqueId(IValidatorType InterpreterType) {
		String id = null;
		do {
			id = String.valueOf(System.currentTimeMillis());
		} while (InterpreterType.findValidator(id) != null
				|| id.equals(fgLastUsedID));
		fgLastUsedID = id;
		return id;
	}

	/**
	 * Compares the given name against current names and adds the appropriate
	 * numerical suffix to ensure that it is unique.
	 *
	 * @param name
	 *                 the name with which to ensure uniqueness
	 * @return the unique version of the given name
	 *
	 */
	protected String generateName(String name) {
		if (!isDuplicateName(name)) {
			return name;
		}

		if (name.matches(".*\\(\\d*\\)")) { //$NON-NLS-1$
			int start = name.lastIndexOf('(');
			int end = name.lastIndexOf(')');
			String stringInt = name.substring(start + 1, end);
			int numericValue = Integer.parseInt(stringInt);
			String newName = name.substring(0, start + 1) + (numericValue + 1)
					+ ")"; //$NON-NLS-1$
			return generateName(newName);
		} else {
			return generateName(name + " (1)"); //$NON-NLS-1$
		}
	}

	protected void copyValidator() {
		// IStructuredSelection selection = (IStructuredSelection)
		// fValidatorList.getSelection();
		// Iterator it = selection.iterator();
		//
		// ArrayList newEntries = new ArrayList();
		// while (it.hasNext()) {
		// IValidator selectedInterpreter = (IValidator) it.next();
		//
		// // duplicate & add Interpreter
		// IValidator standin = new IValidator(selectedInterpreter,
		// createUniqueId(selectedInterpreter.getValidatorType()));
		// standin.setName(generateName(selectedInterpreter.getName()));
		// // AddDLTKInterpreterDialog dialog =
		// createInterpreterDialog(standin);
		// dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_18);
		// if (dialog.open() != Window.OK) {
		// return;
		// }
		// newEntries.add(standin);
		// fValidator.add(standin);
		// }
		// fValidatorList.refresh();
		// fValidatorList.setSelection(new
		// StructuredSelection(newEntries.toArray()));
	}

	/**
	 * Bring up a dialog that lets the user create a new Interpreter definition.
	 */
	protected void addValidator() {
		AddValidatorDialog dialog = new AddValidatorDialog(this, getShell(),
				ValidatorRuntime.getPossibleValidatorTypes(), null);
		dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_7);
		if (dialog.open() != Window.OK) {
			dialog.removeValidators(true);
			return;
		} else {
			dialog.removeValidators(false);
		}
		fValidatorList.refresh();
	}

	protected void editValidator() {
		IStructuredSelection selection = fValidatorList
				.getStructuredSelection();
		IValidator validator = (IValidator) selection.getFirstElement();
		if (validator == null) {
			return;
		}

		AddValidatorDialog dialog = new AddValidatorDialog(this, getShell(),
				ValidatorRuntime.getValidatorTypes(), validator);
		dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_8);
		if (dialog.open() != Window.OK) {
			return;
		}
		fValidatorList.refresh(validator);
	}
}
