/*******************************************************************************
 * Copyright (c) 2008, 2017 xored software, Inc. 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 (Yuri Strot)
 *******************************************************************************/
package org.eclipse.dltk.ui.formatter.internal;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKContributionExtensionManager;
import org.eclipse.dltk.core.IDLTKContributedExtension;
import org.eclipse.dltk.core.IPreferencesLookupDelegate;
import org.eclipse.dltk.core.IPreferencesSaveDelegate;
import org.eclipse.dltk.internal.ui.util.SWTUtil;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.dialogs.PropertyLinkArea;
import org.eclipse.dltk.ui.formatter.AlreadyExistsDialog;
import org.eclipse.dltk.ui.formatter.CreateProfileDialog;
import org.eclipse.dltk.ui.formatter.FormatterMessages;
import org.eclipse.dltk.ui.formatter.IFormatterModifyDialog;
import org.eclipse.dltk.ui.formatter.IFormatterModifyDialogOwner;
import org.eclipse.dltk.ui.formatter.IProfile;
import org.eclipse.dltk.ui.formatter.IProfileManager;
import org.eclipse.dltk.ui.formatter.IProfileStore;
import org.eclipse.dltk.ui.formatter.IProfileVersioner;
import org.eclipse.dltk.ui.formatter.IScriptFormatterFactory;
import org.eclipse.dltk.ui.formatter.ProfileKind;
import org.eclipse.dltk.ui.formatter.ScriptFormatterManager;
import org.eclipse.dltk.ui.preferences.AbstractOptionsBlock;
import org.eclipse.dltk.ui.preferences.PreferenceKey;
import org.eclipse.dltk.ui.util.IStatusChangeListener;
import org.eclipse.dltk.ui.util.PixelConverter;
import org.eclipse.dltk.ui.util.SWTFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.dialogs.PreferenceLinkArea;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

public abstract class AbstractFormatterSelectionBlock
		extends AbstractOptionsBlock {

	protected abstract IFormatterModifyDialogOwner createDialogOwner();

	/**
	 * Returns the extension manager for the contributed extension.
	 */
	protected abstract DLTKContributionExtensionManager getExtensionManager();

	/**
	 * Returns the message that will be used to create the link to the
	 * preference or property page.
	 */
	protected abstract String getPreferenceLinkMessage();

	/**
	 * Returns the preference key that will be used to store the contribution
	 * preference.
	 */
	protected abstract PreferenceKey getSavedContributionKey();

	protected abstract void updatePreview();

	protected abstract SourceViewer createPreview(Composite parent);

	public AbstractFormatterSelectionBlock(IStatusChangeListener context,
			IProject project, PreferenceKey formatterKey, String natureId,
			IWorkbenchPreferenceContainer container) {
		super(context, project,
				collectPreferenceKeys(TEMP_LIST, natureId, formatterKey),
				container);
		factories = TEMP_LIST
				.toArray(new IScriptFormatterFactory[TEMP_LIST.size()]);
		TEMP_LIST = new ArrayList();
	}

	protected IProfileManager getProfileManager() {
		return getProfileManager(getSelectedExtension());
	}

	protected IProfileManager getProfileManager(
			IScriptFormatterFactory factory) {
		IProfileManager manager = profileByFactory.get(factory);
		if (manager == null) {
			List<IProfile> allProfiles = new ArrayList<>();
			List<IProfile> buitinProfiles = factory.getBuiltInProfiles();
			if (buitinProfiles != null && buitinProfiles.size() > 0) {
				allProfiles.addAll(buitinProfiles);
			} else {
				DLTKUIPlugin.logErrorMessage(NLS.bind(
						FormatterMessages.AbstractFormatterSelectionBlock_noBuiltInProfiles,
						factory.getId()));
			}
			allProfiles.addAll(factory.getCustomProfiles());
			manager = factory.createProfileManager(allProfiles);
			selectCurrentProfile(factory, manager);
			profileByFactory.put(factory, manager);
		}
		return manager;
	}

	private void selectCurrentProfile(IScriptFormatterFactory factory,
			IProfileManager manager) {
		PreferenceKey activeProfileKey = factory.getActiveProfileKey();
		if (activeProfileKey != null) {
			String profileId = getValue(activeProfileKey);
			if (profileId != null && profileId.length() != 0) {
				IProfile profile = manager.findProfile(profileId);
				if (profile != null) {
					manager.setSelected(profile);
					return;
				}
			}
		}
		Map<String, String> preferences = factory
				.retrievePreferences(new LoadDelegate());
		if (!preferences.isEmpty()) {
			for (IProfile profile : manager.getSortedProfiles()) {
				if (profile.equalsTo(preferences)) {
					manager.setSelected(profile);
					return;
				}
			}
		}
		String name = getProfileName(manager.getSortedProfiles(),
				FormatterMessages.AbstractFormatterSelectionBlock_activeProfileName);
		IProfile profile = manager.create(ProfileKind.CUSTOM, name, preferences,
				factory.getId(),
				factory.getProfileVersioner().getCurrentVersion());
		manager.setSelected(profile);
	}

	protected String getProfileName(List<IProfile> profiles, String prefix) {
		HashSet<String> names = new HashSet<>(profiles.size());
		for (IProfile profile : profiles) {
			names.add(profile.getName());
		}
		if (!names.contains(prefix))
			return prefix;
		for (int i = 2;; i++) {
			String name = prefix + " " + i; //$NON-NLS-1$
			if (!names.contains(name))
				return name;
		}
	}

	protected IProfile findProfile(Map<String, String> preferences,
			List<IProfile> profiles) {
		for (IProfile profile : profiles) {
			if (profile.equalsTo(preferences))
				return profile;
		}
		return null;
	}

	@Override
	protected boolean saveValues() {
		for (Map.Entry<IScriptFormatterFactory, IProfileManager> entry : profileByFactory
				.entrySet()) {
			final IProfileManager manager = entry.getValue();
			if (manager.isDirty()) {
				entry.getKey().saveCustomProfiles(manager.getSortedProfiles());
				manager.clearDirty();
			}
		}
		return super.saveValues();
	}

	protected void applyPreferences() {
		IScriptFormatterFactory factory = getSelectedExtension();
		IProfileManager manager = getProfileManager(factory);
		IProfile profile = manager.getSelected();
		Map<String, String> settings = new HashMap<>();
		if (profile != null) {
			settings.putAll(profile.getSettings());
		}
		PreferenceKey activeProfileKey = factory.getActiveProfileKey();
		if (activeProfileKey != null) {
			if (profile != null) {
				settings.put(activeProfileKey.getName(), profile.getID());
			} else {
				settings.remove(activeProfileKey.getName());
			}
		}
		IPreferencesSaveDelegate delegate = new SaveDelegate();
		factory.savePreferences(settings, delegate);
		updatePreview();
	}

	@Override
	public void performDefaults() {
		super.performDefaults();
		final IProfileManager profileManager = getProfileManager();
		profileManager.setSelected(profileManager.getSortedProfiles().get(0));
		updateComboFromProfiles();
		updateSelection();
	}

	protected static PreferenceKey[] collectPreferenceKeys(List factories,
			String natureId, PreferenceKey formatterKey) {
		List<PreferenceKey> result = new ArrayList<>();
		result.add(formatterKey);
		IDLTKContributedExtension[] extensions = ScriptFormatterManager
				.getInstance().getContributions(natureId);
		for (int i = 0; i < extensions.length; ++i) {
			IScriptFormatterFactory factory = (IScriptFormatterFactory) extensions[i];
			factories.add(factory);
			final PreferenceKey[] keys = factory.getPreferenceKeys();
			if (keys != null) {
				Collections.addAll(result, keys);
			}
			final PreferenceKey profile = factory.getActiveProfileKey();
			if (profile != null) {
				result.add(profile);
			}
		}
		return result.toArray(new PreferenceKey[result.size()]);
	}

	// ~ Methods

	@Override
	public final Control createOptionsBlock(Composite parent) {
		initializeProjectSettings();
		return createSelectorBlock(parent);
	}

	protected Composite createDescription(Composite parent,
			IDLTKContributedExtension contrib) {
		Composite composite = SWTFactory.createComposite(parent,
				parent.getFont(), 1, 1, GridData.FILL);

		String desc = contrib.getDescription();
		if (desc == null) {
			desc = Util.EMPTY_STRING;
		}
		SWTFactory.createLabel(composite, desc, 1);

		String prefPageId = contrib.getPreferencePageId();
		String propPageId = contrib.getPropertyPageId();

		// we're a property page
		if (isProjectPreferencePage() && hasValidId(propPageId)) {
			new PropertyLinkArea(composite, SWT.NONE, propPageId, fProject,
					getPreferenceLinkMessage(), getPreferenceContainer());
		}

		// we're a preference page
		if (!isProjectPreferencePage() && hasValidId(prefPageId)) {
			new PreferenceLinkArea(composite, SWT.NONE, prefPageId,
					getPreferenceLinkMessage(), getPreferenceContainer(), null);
		}

		return composite;
	}

	protected Composite createSelectorBlock(Composite parent) {
		final int numColumns = 5;

		PixelConverter fPixConv = new PixelConverter(parent);
		fComposite = createComposite(parent, numColumns);

		createFormatterSection(fComposite, numColumns, fPixConv);

		final Group group = SWTFactory.createGroup(fComposite,
				FormatterMessages.AbstractFormatterSelectionBlock_profilesGroup,
				numColumns, numColumns, GridData.FILL_BOTH);

		Label profileLabel = new Label(group, SWT.NONE);
		profileLabel.setText(
				FormatterMessages.AbstractFormatterSelectionBlock_activeProfile);
		GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
		data.horizontalSpan = numColumns;
		profileLabel.setLayoutData(data);

		fProfileCombo = createProfileCombo(group, 3,
				fPixConv.convertWidthInCharsToPixels(20));
		updateComboFromProfiles();
		fProfileCombo.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				updateSelection();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				updateSelection();
			}
		});

		fEditButton = createButton(group,
				FormatterMessages.AbstractFormatterSelectionBlock_editProfile,
				GridData.HORIZONTAL_ALIGN_BEGINNING);
		fEditButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				editButtonPressed();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				editButtonPressed();
			}
		});
		fDeleteButton = createButton(group,
				FormatterMessages.AbstractFormatterSelectionBlock_removeProfile,
				GridData.HORIZONTAL_ALIGN_BEGINNING);
		fDeleteButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				doDelete();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				doDelete();
			}

			protected void doDelete() {
				IProfileManager profileManager = getProfileManager();
				IProfile selected = profileManager.getSelected();
				if (MessageDialog.openQuestion(group.getShell(),
						FormatterMessages.AbstractFormatterSelectionBlock_confirmRemoveLabel,
						NLS.bind(
								FormatterMessages.AbstractFormatterSelectionBlock_confirmRemoveMessage,
								selected.getName()))) {
					profileManager.deleteProfile(selected);
					updateComboFromProfiles();
					applyPreferences();
				}
			}
		});

		fNewButton = createButton(group,
				FormatterMessages.AbstractFormatterSelectionBlock_newProfile,
				GridData.HORIZONTAL_ALIGN_BEGINNING);
		fNewButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				createNewProfile();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				createNewProfile();
			}

			protected void createNewProfile() {
				IScriptFormatterFactory formatterFactory = getSelectedExtension();
				final CreateProfileDialog p = new CreateProfileDialog(
						group.getShell(), getProfileManager(),
						formatterFactory.getProfileVersioner());
				if (p.open() != Window.OK)
					return;

				applyPreferences();

				updateComboFromProfiles();
				if (!p.openEditDialog())
					return;
				editButtonPressed();
			}
		});

		fLoadButton = createButton(group,
				FormatterMessages.AbstractFormatterSelectionBlock_importProfile,
				GridData.HORIZONTAL_ALIGN_END);
		fLoadButton.addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				doImport();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				doImport();
			}

			protected void doImport() {
				final FileDialog dialog = new FileDialog(group.getShell(),
						SWT.OPEN);
				dialog.setText(
						FormatterMessages.AbstractFormatterSelectionBlock_importProfileLabel);
				dialog.setFilterExtensions(new String[] { "*.xml" }); //$NON-NLS-1$
				final String path = dialog.open();
				if (path == null)
					return;

				final File file = new File(path);
				IScriptFormatterFactory factory = getSelectedExtension();
				Collection<IProfile> profiles = null;
				IProfileStore store = factory.getProfileStore();
				try {
					profiles = store.readProfilesFromFile(file);
				} catch (CoreException e) {
					DLTKUIPlugin.logErrorMessage(
							FormatterMessages.AbstractFormatterSelectionBlock_notValidProfile,
							e);
				}
				if (profiles == null || profiles.isEmpty())
					return;

				final IProfile profile = profiles.iterator().next();

				IProfileVersioner versioner = factory.getProfileVersioner();

				if (!versioner.getFormatterId()
						.equals(profile.getFormatterId())) {
					final String title = FormatterMessages.AbstractFormatterSelectionBlock_importProfileLabel;
					final String message = NLS.bind(
							FormatterMessages.AbstractFormatterSelectionBlock_notValidFormatter,
							versioner.getFormatterId(),
							profile.getFormatterId());
					MessageDialog.openError(group.getShell(), title, message);
					return;
				}

				if (profile.getVersion() > versioner.getCurrentVersion()) {
					final String title = FormatterMessages.AbstractFormatterSelectionBlock_importingProfile;
					final String message = FormatterMessages.AbstractFormatterSelectionBlock_moreRecentVersion;
					MessageDialog.openWarning(group.getShell(), title, message);
				}

				final IProfileManager profileManager = getProfileManager();
				if (profileManager.containsName(profile.getName())) {
					final AlreadyExistsDialog aeDialog = new AlreadyExistsDialog(
							group.getShell(), profile, profileManager);
					if (aeDialog.open() != Window.OK)
						return;
				}
				((IProfile.ICustomProfile) profile)
						.setVersion(versioner.getCurrentVersion());
				profileManager.addProfile(profile);
				updateComboFromProfiles();
				applyPreferences();
			}
		});
		createLabel(group, "", 3); //$NON-NLS-1$

		configurePreview(group, numColumns);
		updateButtons();
		applyPreferences();

		return fComposite;
	}

	protected void createFormatterSection(Composite composite, int numColumns,
			PixelConverter fPixConv) {
		String id = getValue(getSavedContributionKey());
		int index = -1;
		for (int i = 0; i < factories.length; i++) {
			IScriptFormatterFactory factory = factories[i];
			if (factory.getId().equals(id)) {
				index = i;
				break;
			}
		}
		if (index == -1 && factories.length != 0) {
			index = 0;
			for (int i = 1; i < factories.length; i++) {
				if (factories[i].getPriority() > factories[index]
						.getPriority()) {
					index = i;
				}
			}
			// doSetFactory(index);
		}

		if (factories.length > 1) {
			createLabel(composite,
					FormatterMessages.AbstractFormatterSelectionBlock_formatterLabel,
					numColumns);
			fFactoryCombo = createProfileCombo(composite, numColumns,
					fPixConv.convertWidthInCharsToPixels(20));

			for (int i = 0; i < factories.length; i++) {
				fFactoryCombo.add(factories[i].getName());
			}

			fFactoryCombo.addSelectionListener(new SelectionListener() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					doSetFactory(fFactoryCombo.getSelectionIndex());
				}

				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					doSetFactory(fFactoryCombo.getSelectionIndex());
				}
			});
			fFactoryCombo.select(index);
		}

		fFactoryDescription = createLabel(composite, "", numColumns, true);
		doSetFactory(index);
	}

	protected void doSetFactory(int index) {
		selectedFactory = index;
		setValue(getSavedContributionKey(), factories[index].getId());
		String desc = getSelectedExtension().getDescription();
		if (desc != null && desc.length() != 0) {
			fFactoryDescription.setText(desc);
		} else {
			fFactoryDescription.setVisible(false);
			GridData data = (GridData) fFactoryDescription.getLayoutData();
			data.exclude = true;
		}
		updateComboFromProfiles();
		applyPreferences();
	}

	protected void configurePreview(Composite composite, int numColumns) {
		createLabel(composite,
				FormatterMessages.AbstractFormatterSelectionBlock_preview,
				numColumns);
		fPreviewViewer = createPreview(composite);

		final GridData gd = new GridData(
				GridData.FILL_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL);
		gd.horizontalSpan = numColumns;
		gd.verticalSpan = 7;
		gd.heightHint = 100;
		fPreviewViewer.getControl().setLayoutData(gd);
	}

	protected IScriptFormatterFactory getSelectedExtension() {
		return factories[selectedFactory];
	}

	protected final void updateSelection() {
		IProfile selected = getProfileManager().getSortedProfiles()
				.get(fProfileCombo.getSelectionIndex());
		getProfileManager().setSelected(selected);
		updateButtons();
		applyPreferences();
		updatePreview();
	}

	protected void editButtonPressed() {
		IScriptFormatterFactory factory = getSelectedExtension();
		if (factory != null) {
			final IProfileManager manager = getProfileManager();
			final IFormatterModifyDialog dialog = factory
					.createDialog(createDialogOwner());
			if (dialog != null) {
				dialog.setProfileManager(manager);
				IProfile profile = manager.getSelected();
				dialog.setPreferences(profile.getSettings());
				if (dialog.open() == Window.OK) {
					profile = manager.getSelected();
					updateComboFromProfiles();
					final Map<String, String> newSettings = dialog
							.getPreferences();
					if (!profile.getSettings().equals(newSettings)) {
						profile.setSettings(newSettings);
						manager.markDirty();
						applyPreferences();
					}
				}
			}
		}
	}

	protected void updateComboFromProfiles() {
		if (fProfileCombo != null && !fProfileCombo.isDisposed()) {
			fProfileCombo.removeAll();

			List<IProfile> profiles = getProfileManager().getSortedProfiles();
			IProfile selected = getProfileManager().getSelected();
			int selection = 0, index = 0;
			for (IProfile profile : profiles) {
				fProfileCombo.add(profile.getName());
				if (profile.equals(selected))
					selection = index;
				index++;
			}
			fProfileCombo.select(selection);
			updateButtons();
		}
	}

	protected void updateButtons() {
		if (fDeleteButton != null && !fDeleteButton.isDisposed()) {
			IProfile selected = getProfileManager().getSelected();
			fDeleteButton.setEnabled(!selected.isBuiltInProfile());
		}
	}

	private class LoadDelegate implements IPreferencesLookupDelegate {

		@Override
		public boolean getBoolean(String qualifier, String key) {
			return getBooleanValue(new PreferenceKey(qualifier, key));
		}

		@Override
		public int getInt(String qualifier, String key) {
			return getIntValue(new PreferenceKey(qualifier, key));
		}

		@Override
		public String getString(String qualifier, String key) {
			return getValue(new PreferenceKey(qualifier, key));
		}

	}

	private class SaveDelegate implements IPreferencesSaveDelegate {

		@Override
		public void setBoolean(String qualifier, String key, boolean value) {
			setValue(new PreferenceKey(qualifier, key), value);
		}

		@Override
		public void setInt(String qualifier, String key, int value) {
			setValue(new PreferenceKey(qualifier, key), String.valueOf(value));
		}

		@Override
		public void setString(String qualifier, String key, String value) {
			setValue(new PreferenceKey(qualifier, key), value);
		}

	}

	private Composite createComposite(Composite parent, int numColumns) {
		final Composite composite = new Composite(parent, SWT.NONE);
		composite.setFont(parent.getFont());

		final GridLayout layout = new GridLayout(numColumns, false);
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);
		return composite;
	}

	private static Combo createProfileCombo(Composite composite, int span,
			int widthHint) {
		final GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = span;
		gd.widthHint = widthHint;

		final Combo combo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
		combo.setFont(composite.getFont());
		combo.setLayoutData(gd);

		return combo;
	}

	private static Button createButton(Composite composite, String text,
			final int style) {
		final Button button = new Button(composite, SWT.PUSH);
		button.setFont(composite.getFont());
		button.setText(text);

		final GridData gd = new GridData(style);
		gd.widthHint = SWTUtil.getButtonWidthHint(button);
		button.setLayoutData(gd);
		return button;
	}

	protected static Label createLabel(Composite composite, String text,
			int numColumns) {
		return createLabel(composite, text, numColumns, false);
	}

	protected static Label createLabel(Composite composite, String text,
			int numColumns, boolean wrap) {
		final GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = numColumns;
		if (wrap) {
			gd.heightHint = new PixelConverter(composite)
					.convertHeightInCharsToPixels(2);
		}

		final Label label = new Label(composite, wrap ? SWT.WRAP : SWT.NONE);
		label.setFont(composite.getFont());
		label.setText(text);
		label.setLayoutData(gd);
		return label;
	}

	private boolean hasValidId(String id) {
		return (id != null && !"".equals(id)); //$NON-NLS-1$
	}

	private Composite fComposite;
	private Combo fProfileCombo;
	private Combo fFactoryCombo;
	private Label fFactoryDescription;
	private Button fEditButton;
	private Button fDeleteButton;
	private Button fNewButton;
	private Button fLoadButton;

	private int selectedFactory;
	private IScriptFormatterFactory[] factories;
	private Map<IScriptFormatterFactory, IProfileManager> profileByFactory = new HashMap<>();
	protected SourceViewer fPreviewViewer;

	private static List<IScriptFormatterFactory> TEMP_LIST = new ArrayList<>();

}
