/*******************************************************************************
 * Copyright (c) 2004, 2014 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *     Perforce - fixes for bug 318396
 *******************************************************************************/

package org.eclipse.mylyn.internal.tasks.ui.editors;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil;
import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskDiffUtil;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.internal.tasks.ui.views.UpdateRepositoryConfigurationAction;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.sync.TaskJob;
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor;
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint;
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.ColumnSpan;
import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.RowSpan;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.progress.IProgressConstants2;

/**
 * Editor part that shows {@link TaskAttribute}s in a two column layout.
 *
 * @author Steffen Pingel
 * @author Kevin Sawicki
 */
public abstract class AbstractTaskEditorAttributeSection extends AbstractTaskEditorSection {

	private static final int LABEL_WIDTH = 110;

	private static final int COLUMN_WIDTH = 140;

	private static final int COLUMN_GAP = 20;

	private static final int MULTI_COLUMN_WIDTH = COLUMN_WIDTH + 5 + COLUMN_GAP + LABEL_WIDTH + 5 + COLUMN_WIDTH;

	private static final int MULTI_ROW_HEIGHT = 55;

	private List<AbstractAttributeEditor> attributeEditors;

	private boolean hasIncoming;

	private Composite attributesComposite;

	private boolean needsRefresh;

	public AbstractTaskEditorAttributeSection() {
	}

	@Override
	public void createControl(Composite parent, final FormToolkit toolkit) {
		initialize();
		super.createControl(parent, toolkit);
	}

	public boolean hasIncoming() {
		return hasIncoming;
	}

	public void selectReveal(TaskAttribute attribute) {
		if (attribute == null) {
			return;
		}
		if (!getSection().isExpanded()) {
			CommonFormUtil.setExpanded(getSection(), true);
		}
		EditorUtil.reveal(getTaskEditorPage().getManagedForm().getForm(), attribute.getId());
	}

	@Override
	public boolean setFormInput(Object input) {
		if (input instanceof String) {
			String text = (String) input;
			Collection<TaskAttribute> attributes = getAttributes();
			for (TaskAttribute attribute : attributes) {
				if (text.equals(attribute.getId())) {
					selectReveal(attribute);
				}
			}
		}
		return super.setFormInput(input);
	}

	private void createAttributeControls(Composite attributesComposite, FormToolkit toolkit, int columnCount) {
		int currentColumn = 1;
		int currentPriority = 0;
		for (AbstractAttributeEditor attributeEditor : attributeEditors) {
			int priority = (attributeEditor.getLayoutHint() != null)
					? attributeEditor.getLayoutHint().getPriority()
					: LayoutHint.DEFAULT_PRIORITY;
			if (priority != currentPriority) {
				currentPriority = priority;
				if (currentColumn > 1) {
					while (currentColumn <= columnCount) {
						getManagedForm().getToolkit().createLabel(attributesComposite, ""); //$NON-NLS-1$
						currentColumn++;
					}
					currentColumn = 1;
				}
			}

			if (attributeEditor.hasLabel()) {
				attributeEditor.createLabelControl(attributesComposite, toolkit);
				Label label = attributeEditor.getLabelControl();
				String text = label.getText();
				String shortenText = TaskDiffUtil.shortenText(label, text, LABEL_WIDTH);
				label.setText(shortenText);
				if (!text.equals(shortenText)) {
					label.setToolTipText(text);
				}
				GridData gd = GridDataFactory.fillDefaults()
						.align(SWT.RIGHT, SWT.CENTER)
						.hint(LABEL_WIDTH, SWT.DEFAULT)
						.create();
				if (currentColumn > 1) {
					gd.horizontalIndent = COLUMN_GAP;
					gd.widthHint = LABEL_WIDTH + COLUMN_GAP;
				}
				label.setLayoutData(gd);
				currentColumn++;
			}

			attributeEditor.createControl(attributesComposite, toolkit);
			LayoutHint layoutHint = attributeEditor.getLayoutHint();
			GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false);
			RowSpan rowSpan = (layoutHint != null && layoutHint.rowSpan != null) ? layoutHint.rowSpan : RowSpan.SINGLE;
			ColumnSpan columnSpan = (layoutHint != null && layoutHint.columnSpan != null)
					? layoutHint.columnSpan
					: ColumnSpan.SINGLE;
			gd.horizontalIndent = 1;// prevent clipping of decorators on Windows
			if (rowSpan == RowSpan.SINGLE && columnSpan == ColumnSpan.SINGLE) {
				gd.widthHint = COLUMN_WIDTH;
				gd.horizontalSpan = 1;
			} else {
				if (rowSpan == RowSpan.MULTIPLE) {
					gd.heightHint = MULTI_ROW_HEIGHT;
				}
				if (columnSpan == ColumnSpan.SINGLE) {
					gd.widthHint = COLUMN_WIDTH;
					gd.horizontalSpan = 1;
				} else {
					gd.widthHint = MULTI_COLUMN_WIDTH;
					gd.horizontalSpan = columnCount - currentColumn + 1;
				}
			}
			attributeEditor.getControl().setLayoutData(gd);

			getTaskEditorPage().getAttributeEditorToolkit().adapt(attributeEditor);

			currentColumn += gd.horizontalSpan;
			currentColumn %= columnCount;
		}
	}

	private void initialize() {
		attributeEditors = new ArrayList<AbstractAttributeEditor>();
		hasIncoming = false;

		Collection<TaskAttribute> attributes = getAttributes();
		for (TaskAttribute attribute : attributes) {
			AbstractAttributeEditor attributeEditor = createAttributeEditor(attribute);
			if (attributeEditor != null) {
				attributeEditors.add(attributeEditor);
				if (getModel().hasIncomingChanges(attribute)) {
					hasIncoming = true;
				}
			}
		}

		Comparator<AbstractAttributeEditor> attributeSorter = createAttributeEditorSorter();
		if (attributeSorter != null) {
			Collections.sort(attributeEditors, attributeSorter);
		}
	}

	/**
	 * Create a comparator by which attribute editors will be sorted. By default attribute editors are sorted by layout
	 * hint priority. Subclasses may override this method to sort attribute editors in a custom way.
	 *
	 * @return comparator for {@link AbstractAttributeEditor} objects
	 */
	protected Comparator<AbstractAttributeEditor> createAttributeEditorSorter() {
		return new Comparator<AbstractAttributeEditor>() {
			public int compare(AbstractAttributeEditor o1, AbstractAttributeEditor o2) {
				int p1 = (o1.getLayoutHint() != null) ? o1.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY;
				int p2 = (o2.getLayoutHint() != null) ? o2.getLayoutHint().getPriority() : LayoutHint.DEFAULT_PRIORITY;
				return p1 - p2;
			}
		};
	}

	@Override
	protected Control createContent(FormToolkit toolkit, Composite parent) {
		attributesComposite = toolkit.createComposite(parent);
		attributesComposite.addListener(SWT.MouseDown, new Listener() {
			public void handleEvent(Event event) {
				Control focus = event.display.getFocusControl();
				if (focus instanceof Text && ((Text) focus).getEditable() == false) {
					getManagedForm().getForm().setFocus();
				}
			}
		});

		GridLayout attributesLayout = EditorUtil.createSectionClientLayout();
		attributesLayout.numColumns = 4;
		attributesLayout.horizontalSpacing = 9;
		attributesLayout.verticalSpacing = 6;
		attributesComposite.setLayout(attributesLayout);

		GridData attributesData = new GridData(GridData.FILL_BOTH);
		attributesData.horizontalSpan = 1;
		attributesData.grabExcessVerticalSpace = false;
		attributesComposite.setLayoutData(attributesData);

		createAttributeControls(attributesComposite, toolkit, attributesLayout.numColumns);
		toolkit.paintBordersFor(attributesComposite);

		return attributesComposite;
	}

	protected IAction doCreateRefreshAction() {
		UpdateRepositoryConfigurationAction repositoryConfigRefresh = new UpdateRepositoryConfigurationAction() {
			@Override
			public void run() {
				getTaskEditorPage().showEditorBusy(true);
				final TaskJob job = TasksUiInternal.getJobFactory().createUpdateRepositoryConfigurationJob(
						getTaskEditorPage().getConnector(), getTaskEditorPage().getTaskRepository(),
						getTaskEditorPage().getTask());
				job.addJobChangeListener(new JobChangeAdapter() {
					@Override
					public void done(IJobChangeEvent event) {
						PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
							public void run() {
								getTaskEditorPage().showEditorBusy(false);
								if (job.getStatus() != null) {
									getTaskEditorPage().getTaskEditor().setStatus(
											Messages.TaskEditorAttributePart_Updating_of_repository_configuration_failed,
											Messages.TaskEditorAttributePart_Update_Failed, job.getStatus());
								} else {
									getTaskEditorPage().refresh();
								}
							}
						});
					}
				});
				job.setUser(true);
				// show the progress in the system task bar if this is a user job (i.e. forced)
				job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE);
				job.setPriority(Job.INTERACTIVE);
				job.schedule();
			};
		};
		repositoryConfigRefresh.setImageDescriptor(TasksUiImages.REPOSITORY_SYNCHRONIZE_SMALL);
		repositoryConfigRefresh.selectionChanged(new StructuredSelection(getTaskEditorPage().getTaskRepository()));
		repositoryConfigRefresh.setToolTipText(Messages.TaskEditorAttributePart_Refresh_Attributes);
		return repositoryConfigRefresh;
	}

	@Override
	protected void fillToolBar(ToolBarManager toolBar) {
		if (needsRefresh()) {
			IAction repositoryConfigRefresh = doCreateRefreshAction();
			toolBar.add(repositoryConfigRefresh);
		}
	}

	/**
	 * Returns the list of attributes that are show in the section.
	 */
	protected abstract Collection<TaskAttribute> getAttributes();

	@Override
	protected String getInfoOverlayText() {
		StringBuilder sb = new StringBuilder();
		List<TaskAttribute> overlayAttributes = getOverlayAttributes();
		for (TaskAttribute attribute : overlayAttributes) {
			String label = getModel().getTaskData().getAttributeMapper().getValueLabel(attribute);
			if (label != null) {
				if (sb.length() > 0) {
					sb.append(" / "); //$NON-NLS-1$
				}
			}
			sb.append(label);
		}
		return (sb.length() > 0) ? sb.toString() : null;
	}

	/**
	 * Returns the attributes that are shown in the overlay text.
	 *
	 * @see #getInfoOverlayText()
	 */
	protected abstract List<TaskAttribute> getOverlayAttributes();

	protected boolean needsRefresh() {
		return needsRefresh;
	}

	protected void setNeedsRefresh(boolean needsRefresh) {
		this.needsRefresh = needsRefresh;
	}

	/**
	 * Integrator requested the ability to control whether the attributes section is expanded on creation.
	 */
	@Override
	protected boolean shouldExpandOnCreate() {
		return getTaskData().isNew() || hasIncoming;
	}

}
