/*******************************************************************************
 * Copyright (c) 2004, 2010 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
 *******************************************************************************/

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

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

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory;
import org.eclipse.mylyn.internal.tasks.core.ITaskList;
import org.eclipse.mylyn.internal.tasks.core.TaskCategory;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.editors.RepositoryTextViewerConfiguration.Mode;
import org.eclipse.mylyn.internal.tasks.ui.util.AbstractRetrieveTitleFromUrlJob;
import org.eclipse.mylyn.internal.tasks.ui.util.TaskContainerComparator;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.Section;

/**
 * @author Steffen Pingel
 */
public class AttributePart extends AbstractLocalEditorPart {

	private ImageHyperlink fetchUrlLink;

	private RichTextEditor urlEditor;

	private CCombo categoryChooser;

	protected AbstractTaskCategory category;

	private Label categoryLabel;

	private List<AbstractTaskCategory> categories;

	public AttributePart() {
		super(Messages.TaskPlanningEditor_Attributes);
	}

	@Override
	public void commit(boolean onSave) {
		if (category != null) {
			TasksUiPlugin.getTaskList().addTask(getTask(), category);
			category = null;
			clearState(categoryChooser);
		}
		getTask().setUrl(urlEditor.getText());
		clearState(urlEditor.getControl());
		super.commit(onSave);
	}

	@Override
	public Control createControl(Composite parent, FormToolkit toolkit) {
		int style = ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE;
//				| ExpandableComposite.LEFT_TEXT_CLIENT_ALIGNMENT;
		if (getTask().getUrl() != null && getTask().getUrl().length() > 0) {
			style |= ExpandableComposite.EXPANDED;
		}

		Section section = createSection(parent, toolkit, style);
		GridDataFactory.fillDefaults().grab(true, false).applyTo(section);
		section.setText(Messages.TaskPlanningEditor_Attributes);
		GridDataFactory.fillDefaults().grab(true, false).applyTo(section);
		createSectionClient(section, toolkit);
		setSection(toolkit, section);

		Composite composite = toolkit.createComposite(section);
		GridLayout layout = EditorUtil.createSectionClientLayout();
		layout.numColumns = 4;
		composite.setLayout(layout);

		Label label = toolkit.createLabel(composite, Messages.AttributePart_Category_);
		label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));

		createCategoryChooser(composite, toolkit);

		// url
		label = toolkit.createLabel(composite, Messages.TaskPlanningEditor_URL);
		label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
		GridDataFactory.defaultsFor(label).indent(20, 0).applyTo(label);

		Composite urlComposite = toolkit.createComposite(composite);
		GridLayout urlLayout = new GridLayout(2, false);
		urlLayout.verticalSpacing = 0;
		urlLayout.marginWidth = 1;
		urlComposite.setLayout(urlLayout);
		GridDataFactory.fillDefaults().grab(true, false).applyTo(urlComposite);

		urlEditor = new RichTextEditor(getRepository(), SWT.FLAT | SWT.SINGLE, null, null, getTask()) {
			@Override
			protected void valueChanged(String value) {
				updateButtons();
				markDirty(urlEditor.getControl());
			}
		};
		urlEditor.setMode(Mode.URL);
		urlEditor.createControl(urlComposite, toolkit);
		urlEditor.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		urlEditor.getViewer().getControl().setMenu(parent.getMenu());
		GridDataFactory.fillDefaults().grab(true, false).applyTo(urlEditor.getControl());

		fetchUrlLink = toolkit.createImageHyperlink(urlComposite, SWT.NONE);
		fetchUrlLink.setImage(CommonImages.getImage(TasksUiImages.TASK_RETRIEVE));
		fetchUrlLink.setToolTipText(Messages.TaskPlanningEditor_Retrieve_task_description_from_URL);
		fetchUrlLink.addHyperlinkListener(new HyperlinkAdapter() {
			@Override
			public void linkActivated(HyperlinkEvent e) {
				featchUrl(urlEditor.getText());
			}
		});
		toolkit.paintBordersFor(urlComposite);

		toolkit.paintBordersFor(composite);
		section.setClient(composite);
		return section;
	}

	private void createSectionClient(final Section section, FormToolkit toolkit) {
		if (section.getTextClient() == null) {
			final Composite textClient = toolkit.createComposite(section);
			textClient.setBackground(null);
			RowLayout rowLayout = new RowLayout();
			rowLayout.center = true;
			rowLayout.marginLeft = 20;
			rowLayout.marginTop = 1;
			rowLayout.marginBottom = 1;
			textClient.setLayout(rowLayout);

			Label label = toolkit.createLabel(textClient, Messages.AttributePart_Category_);
			label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
			label.setBackground(null);

			categoryLabel = toolkit.createLabel(textClient, ""); //$NON-NLS-1$
			categoryLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE));
			categoryLabel.setBackground(null);

			toolkit.paintBordersFor(textClient);

			section.setTextClient(textClient);
			section.addExpansionListener(new ExpansionAdapter() {
				@Override
				public void expansionStateChanging(ExpansionEvent e) {
					textClient.setVisible(!e.getState());
				}
			});
			textClient.setVisible(!section.isExpanded());
		}
	}

	/**
	 * Set the task summary to the page title from the specified url.
	 */
	private void featchUrl(final String url) {
		AbstractRetrieveTitleFromUrlJob job = new AbstractRetrieveTitleFromUrlJob(urlEditor.getText()) {
			@Override
			protected void titleRetrieved(String pageTitle) {
				IFormPart[] parts = getManagedForm().getParts();
				for (IFormPart part : parts) {
					if (part instanceof SummaryPart) {
						((SummaryPart) part).setSummary(pageTitle);
					}
				}
			}
		};
		job.schedule();
	}

	private void updateButtons() {
		String value = urlEditor.getText();
		fetchUrlLink.setEnabled(value.startsWith("http://") || value.startsWith("https://")); //$NON-NLS-1$ //$NON-NLS-2$
	}

	@Override
	public void refresh(boolean discardChanges) {
		if (shouldRefresh(categoryChooser, discardChanges)) {
			ITaskList taskList = TasksUiInternal.getTaskList();
			categories = new ArrayList<AbstractTaskCategory>(taskList.getCategories());
			Collections.sort(categories, new TaskContainerComparator());

			AbstractTaskCategory selectedCategory = category;
			if (selectedCategory == null) {
				selectedCategory = TaskCategory.getParentTaskCategory(getTask());
			}
			categoryChooser.removeAll();
			int selectedIndex = 0;
			for (int i = 0; i < categories.size(); i++) {
				AbstractTaskCategory category = categories.get(i);
				categoryChooser.add(category.getSummary());
				if (category.equals(selectedCategory)) {
					selectedIndex = i;
				}
			}
			categoryChooser.select(selectedIndex);
			updateCategoryLabel();
		}

		if (shouldRefresh(urlEditor.getControl(), discardChanges)) {
			String url = getTask().getUrl();
			urlEditor.setText(url != null ? url : ""); //$NON-NLS-1$
		}

		updateButtons();
	}

	private void updateCategoryLabel() {
		if (category == null) {
			AbstractTaskCategory parentTaskCategory = TaskCategory.getParentTaskCategory(getTask());
			categoryLabel.setText((parentTaskCategory != null) ? parentTaskCategory.getSummary() : ""); //$NON-NLS-1$
		} else {
			categoryLabel.setText(category.getSummary());
		}
		if (!getSection().isExpanded()) {
			getSection().layout(true, true);
		}
	}

	private void createCategoryChooser(Composite buttonComposite, FormToolkit toolkit) {
		categoryChooser = new CCombo(buttonComposite, SWT.FLAT | SWT.READ_ONLY);
		categoryChooser.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
		toolkit.adapt(categoryChooser, false, false);
		categoryChooser.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				if (categoryChooser.getSelectionIndex() != -1) {
					category = categories.get(categoryChooser.getSelectionIndex());
					updateCategoryLabel();
					markDirty(categoryChooser);
				}
			}
		});
	}

}
