//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.forms;

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

import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.AuthoringUIText;
import org.eclipse.epf.authoring.ui.editors.MethodElementEditor;
import org.eclipse.epf.authoring.ui.filters.ContentFilter;
import org.eclipse.epf.authoring.ui.filters.WorkProductFilter;
import org.eclipse.epf.authoring.ui.richtext.IMethodRichText;
import org.eclipse.epf.authoring.ui.util.UIHelper;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.itemsfilter.FilterConstants;
import org.eclipse.epf.library.edit.itemsfilter.VariabilityBaseElementFilter;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Artifact;
import org.eclipse.epf.uma.ArtifactDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.DeliverableDescription;
import org.eclipse.epf.uma.Outcome;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.forms.editor.FormEditor;


/**
 * The Description page in a Work Product (Artifact, Deliverable and Outcome)
 * editor.
 * 
 * @author Shilpa Toraskar
 * @author Kelvin Low
 * @since 1.0
 */
public class WorkProductDescriptionPage extends DescriptionFormPage {

	private static final String FORM_PAGE_ID = "workProductDescriptionPage"; //$NON-NLS-1$	

	private IMethodRichText ctrl_impact;

	private IMethodRichText ctrl_reason;

	// For Artifact
	private IMethodRichText ctrl_brief_outline;

	private IMethodRichText ctrl_representation_options;

	// For Deliverable
	private IMethodRichText ctrl_external_desc, ctrl_packaging_guidance;

	private WorkProduct workProduct;

	/**
	 * Creates a new instance.
	 */
	public WorkProductDescriptionPage(FormEditor editor) {
		super(editor, FORM_PAGE_ID, AuthoringUIText.DESCRIPTION_PAGE_TITLE);
	}

	/**
	 * @see org.eclipse.ui.forms.editor.init(IEditorSite, IEditorInput)
	 */
	public void init(IEditorSite site, IEditorInput input) {
		super.init(site, input);
		workProduct = (WorkProduct) contentElement;
		purposeOn = true;
		externalIdOn = true;
		if (!(contentElement instanceof Outcome)) {
			notationSectionOn = true;
		}
		tailoringSectionOn = true;
		iconSectionOn = true;
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#createNotationSectionContent()
	 */
	protected void createNotationSectionContent() {
		super.createNotationSectionContent();
		if (workProduct instanceof Artifact) {
			ctrl_brief_outline = createRichTextEditWithLinkForSection(toolkit,
					notationComposite, AuthoringUIText.BRIEF_OUTLINE_TEXT, 40,
					400, NOTATION_SECTION_ID);
			ctrl_representation_options = createRichTextEditWithLinkForSection(
					toolkit, notationComposite,
					AuthoringUIText.REPRESENTATION_OPTIONS_TEXT, 40, 400,
					NOTATION_SECTION_ID);
		} else if (workProduct instanceof Deliverable) {
			ctrl_external_desc = createRichTextEditWithLinkForSection(toolkit,
					notationComposite,
					AuthoringUIText.EXTERNAL_DESCRIPTION_TEXT, 40, 400,
					NOTATION_SECTION_ID);
			ctrl_packaging_guidance = createRichTextEditWithLinkForSection(
					toolkit, notationComposite,
					AuthoringUIText.PACKAGING_GUIDANCE_TEXT, 40, 400,
					NOTATION_SECTION_ID);
		}
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#createTailoringSectionContent()
	 */
	protected void createTailoringSectionContent() {
		super.createTailoringSectionContent();
		ctrl_impact = createRichTextEditWithLinkForSection(toolkit,
				tailoringComposite, AuthoringUIText.IMPACT_OF_NOT_HAVING_TEXT,
				40, 400, TAILORING_SECTION_ID);
		ctrl_reason = createRichTextEditWithLinkForSection(toolkit,
				tailoringComposite,
				AuthoringUIText.REASON_FOR_NOT_NEEDING_TEXT, 40, 400,
				TAILORING_SECTION_ID);
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#addListeners()
	 */
	protected void addListeners() {
		final IActionManager actionMgr = ((MethodElementEditor) getEditor())
				.getActionManager();

		super.addListeners();

		ctrl_purpose.setModalObject(contentElement.getPresentation());
		ctrl_purpose.setModalObjectFeature(UmaPackage.eINSTANCE
				.getWorkProductDescription_Purpose());
		ctrl_purpose.addModifyListener(contentModifyListener);
		ctrl_purpose.addListener(SWT.Deactivate, new Listener() {
			public void handleEvent(Event e) {
				IMethodRichText control = descExpandFlag ? ctrl_expanded
						: ctrl_purpose;
				if (!control.getModified()) {
					return;
				}
				String oldContent = ((org.eclipse.epf.uma.WorkProductDescription) workProduct
						.getPresentation()).getPurpose();
				if (((MethodElementEditor) getEditor()).mustRestoreValue(
						control, oldContent)) {
					return;
				}
				String newContent = control.getText();
				if (!newContent.equals(oldContent)) {
					boolean success = actionMgr.doAction(IActionManager.SET,
							contentElement.getPresentation(),
							UmaPackage.eINSTANCE
									.getWorkProductDescription_Purpose(),
							newContent, -1);
					if (success && isVersionSectionOn()) {
						updateChangeDate();
					}
				}
			}
		});

		ctrl_external_id.addModifyListener(contentModifyListener);
		ctrl_external_id.addFocusListener(new FocusAdapter() {
			public void focusGained(FocusEvent e) {
				((MethodElementEditor) getEditor()).setCurrentFeatureEditor(e.widget,
						UmaPackage.eINSTANCE.getWorkProductDescription_ExternalId());
			}

			public void focusLost(FocusEvent e) {
				String oldContent = ((org.eclipse.epf.uma.WorkProductDescription) workProduct
						.getPresentation()).getExternalId();
				if (((MethodElementEditor) getEditor()).mustRestoreValue(
						ctrl_external_id, oldContent)) {
					return;
				}
				String newContent = ctrl_external_id.getText();
				if (!newContent.equals(oldContent)) {
					boolean success = actionMgr.doAction(IActionManager.SET,
							contentElement.getPresentation(),
							UmaPackage.eINSTANCE
									.getWorkProductDescription_ExternalId(),
							newContent, -1);
					if (success && isVersionSectionOn()) {
						updateChangeDate();
					}
				}
			}
		});

		ctrl_impact.setModalObject(contentElement.getPresentation());
		ctrl_impact.setModalObjectFeature(UmaPackage.eINSTANCE
				.getWorkProductDescription_ImpactOfNotHaving());
		ctrl_impact.addModifyListener(contentModifyListener);
		ctrl_impact.addListener(SWT.Deactivate, new Listener() {
			public void handleEvent(Event e) {
				IMethodRichText control = descExpandFlag ? ctrl_expanded
						: ctrl_impact;
				if (!control.getModified()) {
					return;
				}
				String oldContent = ((org.eclipse.epf.uma.WorkProductDescription) workProduct
						.getPresentation()).getImpactOfNotHaving();
				if (((MethodElementEditor) getEditor()).mustRestoreValue(
						control, oldContent)) {
					return;
				}
				String newContent = control.getText();
				if (!newContent.equals(oldContent)) {
					boolean success = actionMgr
							.doAction(
									IActionManager.SET,
									contentElement.getPresentation(),
									UmaPackage.eINSTANCE
											.getWorkProductDescription_ImpactOfNotHaving(),
									newContent, -1);
					if (success && isVersionSectionOn()) {
						updateChangeDate();
					}
				}
			}
		});

		ctrl_reason.setModalObject(contentElement.getPresentation());
		ctrl_reason.setModalObjectFeature(UmaPackage.eINSTANCE
				.getWorkProductDescription_ReasonsForNotNeeding());
		ctrl_reason.addModifyListener(contentModifyListener);
		ctrl_reason.addListener(SWT.Deactivate, new Listener() {
			public void handleEvent(Event e) {
				IMethodRichText control = descExpandFlag ? ctrl_expanded
						: ctrl_reason;
				if (!control.getModified()) {
					return;
				}
				String oldContent = ((org.eclipse.epf.uma.WorkProductDescription) workProduct
						.getPresentation()).getReasonsForNotNeeding();
				if (((MethodElementEditor) getEditor()).mustRestoreValue(
						control, oldContent)) {
					return;
				}
				String newContent = control.getText();
				if (!newContent.equals(oldContent)) {
					boolean success = actionMgr
							.doAction(
									IActionManager.SET,
									contentElement.getPresentation(),
									UmaPackage.eINSTANCE
											.getWorkProductDescription_ReasonsForNotNeeding(),
									newContent, -1);
					if (success && isVersionSectionOn()) {
						updateChangeDate();
					}
				}
			}
		});

		if (workProduct instanceof Artifact) {
			ctrl_brief_outline.setModalObject(contentElement.getPresentation());
			ctrl_brief_outline.setModalObjectFeature(UmaPackage.eINSTANCE
					.getArtifactDescription_BriefOutline());
			ctrl_brief_outline.addModifyListener(contentModifyListener);
			ctrl_brief_outline.addListener(SWT.Deactivate, new Listener() {
				public void handleEvent(Event e) {
					IMethodRichText control = descExpandFlag ? ctrl_expanded
							: ctrl_brief_outline;
					if (!control.getModified()) {
						return;
					}
					String oldContent = ((org.eclipse.epf.uma.ArtifactDescription) workProduct
							.getPresentation()).getBriefOutline();
					if (((MethodElementEditor) getEditor()).mustRestoreValue(
							control, oldContent)) {
						return;
					}
					String newContent = descExpandFlag ? ctrl_expanded
							.getText() : ctrl_brief_outline.getText();
					if (!newContent.equals(oldContent)) {
						boolean success = actionMgr.doAction(
								IActionManager.SET, contentElement
										.getPresentation(),
								UmaPackage.eINSTANCE
										.getArtifactDescription_BriefOutline(),
								newContent, -1);
						if (success && isVersionSectionOn()) {
							updateChangeDate();
						}
					}
				}
			});

			ctrl_representation_options.setModalObject(contentElement
					.getPresentation());
			ctrl_representation_options
					.setModalObjectFeature(UmaPackage.eINSTANCE
							.getArtifactDescription_RepresentationOptions());
			ctrl_representation_options
					.addModifyListener(contentModifyListener);
			ctrl_representation_options.addListener(SWT.Deactivate,
					new Listener() {
						public void handleEvent(Event e) {
							IMethodRichText control = descExpandFlag ? ctrl_expanded
									: ctrl_representation_options;
							if (!control.getModified()) {
								return;
							}
							String oldContent = ((org.eclipse.epf.uma.ArtifactDescription) workProduct
									.getPresentation())
									.getRepresentationOptions();
							if (((MethodElementEditor) getEditor())
									.mustRestoreValue(control, oldContent)) {
								return;
							}
							String newContent = control.getText();
							if (!newContent.equals(oldContent)) {
								boolean success = actionMgr
										.doAction(
												IActionManager.SET,
												contentElement
														.getPresentation(),
												UmaPackage.eINSTANCE
														.getArtifactDescription_RepresentationOptions(),
												newContent, -1);
								if (success && isVersionSectionOn()) {
									updateChangeDate();
								}
							}
						}
					});
		}

		if (workProduct instanceof Deliverable) {
			ctrl_external_desc.setModalObject(contentElement.getPresentation());
			ctrl_external_desc.setModalObjectFeature(UmaPackage.eINSTANCE
					.getDeliverableDescription_ExternalDescription());
			ctrl_external_desc.addModifyListener(contentModifyListener);
			ctrl_external_desc.addListener(SWT.Deactivate, new Listener() {
				public void handleEvent(Event e) {
					IMethodRichText control = descExpandFlag ? ctrl_expanded
							: ctrl_external_desc;
					if (!control.getModified()) {
						return;
					}
					String oldContent = ((org.eclipse.epf.uma.DeliverableDescription) workProduct
							.getPresentation()).getExternalDescription();
					if (((MethodElementEditor) getEditor()).mustRestoreValue(
							control, oldContent)) {
						return;
					}
					String newContent = control.getText();
					if (!newContent.equals(oldContent)) {
						boolean success = actionMgr
								.doAction(
										IActionManager.SET,
										contentElement.getPresentation(),
										UmaPackage.eINSTANCE
												.getDeliverableDescription_ExternalDescription(),
										newContent, -1);
						if (success && isVersionSectionOn()) {
							updateChangeDate();
						}
					}
				}
			});

			ctrl_packaging_guidance.setModalObject(contentElement
					.getPresentation());
			ctrl_packaging_guidance.setModalObjectFeature(UmaPackage.eINSTANCE
					.getDeliverableDescription_PackagingGuidance());
			ctrl_packaging_guidance.addModifyListener(contentModifyListener);
			ctrl_packaging_guidance.addListener(SWT.Deactivate, new Listener() {
				public void handleEvent(Event e) {
					IMethodRichText control = descExpandFlag ? ctrl_expanded
							: ctrl_packaging_guidance;
					if (!control.getModified()) {
						return;
					}
					String oldContent = ((org.eclipse.epf.uma.DeliverableDescription) workProduct
							.getPresentation()).getPackagingGuidance();
					if (((MethodElementEditor) getEditor()).mustRestoreValue(
							control, oldContent)) {
						return;
					}
					String newContent = control.getText();
					if (!newContent.equals(oldContent)) {
						boolean success = actionMgr
								.doAction(
										IActionManager.SET,
										contentElement.getPresentation(),
										UmaPackage.eINSTANCE
												.getDeliverableDescription_PackagingGuidance(),
										newContent, -1);
						if (success && isVersionSectionOn()) {
							updateChangeDate();
						}
					}
				}
			});
		}
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#refresh(boolean)
	 */
	protected void refresh(boolean editable) {
		super.refresh(editable);
		ctrl_impact.setEditable(editable);
		ctrl_reason.setEditable(editable);
		if (workProduct instanceof Artifact) {
			ctrl_brief_outline.setEditable(editable);
			ctrl_representation_options.setEditable(editable);
		}
		if (workProduct instanceof Deliverable) {
			ctrl_external_desc.setEditable(editable);
			ctrl_packaging_guidance.setEditable(editable);
		}
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#loadData()
	 */
	protected void loadData() {
		super.loadData();

		org.eclipse.epf.uma.WorkProductDescription content = ((org.eclipse.epf.uma.WorkProductDescription) workProduct
				.getPresentation());
		String purpose = content.getPurpose();
		String impact = content.getImpactOfNotHaving();
		String reason = content.getReasonsForNotNeeding();

		ctrl_purpose.setText(purpose == null ? "" : purpose); //$NON-NLS-1$	
		ctrl_impact.setText(impact == null ? "" : impact); //$NON-NLS-1$	
		ctrl_reason.setText(reason == null ? "" : reason); //$NON-NLS-1$

		if (externalIdOn) {
			String external_id = content.getExternalId();
			ctrl_external_id.setText(external_id == null ? "" : external_id); //$NON-NLS-1$
		}

		if (workProduct instanceof Artifact) {
			ctrl_brief_outline
					.setText(((ArtifactDescription) content).getBriefOutline() == null ? "" : ((ArtifactDescription) content).getBriefOutline()); //$NON-NLS-1$
			ctrl_representation_options
					.setText(((ArtifactDescription) content)
							.getRepresentationOptions() == null ? "" : ((ArtifactDescription) content).getRepresentationOptions()); //$NON-NLS-1$
		} else if (workProduct instanceof Deliverable) {
			ctrl_external_desc
					.setText(((DeliverableDescription) content)
							.getExternalDescription() == null ? "" : ((DeliverableDescription) content).getExternalDescription()); //$NON-NLS-1$
			ctrl_packaging_guidance
					.setText(((DeliverableDescription) content)
							.getPackagingGuidance() == null ? "" : ((DeliverableDescription) content).getPackagingGuidance()); //$NON-NLS-1$
		}
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#getContentElement()
	 */
	protected Object getContentElement() {
		return workProduct;
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#getTabString()
	 */
	protected String getTabString() {
		return FilterConstants.WORKPRODUCTS;
	}

	/**
	 * @see org.eclipse.epf.authoring.ui.forms.DescriptionFormPage#getFilter()
	 */
	protected IFilter getFilter() {
		filter = new WorkProductFilter() {
			List badlist = new ArrayList();

			protected boolean childAccept(Object obj) {
				if (super.childAccept(obj)) {
					if (obj instanceof ContentElement) {
						if (obj instanceof WorkProduct
								&& ((ContentElement) getHelper()
										.getContentElement()).getType().equals(
										((ContentElement) obj).getType())) {
							// prevent circular dependency from deliverable
							// parts and variability
							if (obj instanceof Deliverable
									&& workProduct instanceof Deliverable) {
								if (!UIHelper.checkCircularDeliverables(
										(Deliverable) obj,
										(Deliverable) workProduct)) {
									badlist.add(obj);
									return false;
								}
								if (((Deliverable) obj)
										.getVariabilityBasedOnElement() != null) {
									if (!UIHelper
											.checkCircularDeliverables(
													(Deliverable) ((Deliverable) obj)
															.getVariabilityBasedOnElement(),
													(Deliverable) workProduct)) {
										badlist.add(obj);
										return false;
									}
								}
								Iterator it1 = TngUtil
										.getGeneralizers((Deliverable) obj);
								while (it1.hasNext()) {
									VariabilityElement ve = (VariabilityElement) it1
											.next();
									if (ve != null) {
										if (ve.equals(obj))
											return false;
										if (!UIHelper
												.checkCircularDeliverables(
														(Deliverable) ve,
														(Deliverable) workProduct)) {
											badlist.add(obj);
											return false;
										}
									}

								}
								// browse through badlist and its deliverable
								// parts.
								List templist = new ArrayList();
								for (Iterator iterator = badlist.iterator(); iterator
										.hasNext();) {
									Object bad = iterator.next();
									UIHelper.deliverablePartsChain(
											(Deliverable) bad, templist);
								}
								if (templist.contains(obj))
									return false;
							}

							return true;
						}
					}
				}
				return false;
			}
		};

		// set additional filter for variability base element checking
		((ContentFilter) filter)
				.setAdditionalFilters(new IFilter[] { new VariabilityBaseElementFilter(
						workProduct) });
		return filter;
	}
	public void loadSectionDescription() {
		if(contentElement instanceof Artifact){
			this.generalSectionDescription = AuthoringUIResources.artifact_generalInfoSection_desc;
			this.detailSectionDescription = AuthoringUIResources.artifact_detailSection_desc;
			this.variabilitySectionDescription = AuthoringUIResources.artifact_variabilitySection_desc;
			this.versionSectionDescription = AuthoringUIResources.artifact_versionInfoSection_desc;
			this.notationSectionDescription = AuthoringUIResources.artifact_notationSection_desc;
			this.tailoringSectionDescription = AuthoringUIResources.artifact_tailoringSection_desc;
			this.iconSectionDescription = AuthoringUIResources.artifact_iconSection_desc;
		}
		if(contentElement instanceof Outcome){
			this.generalSectionDescription = AuthoringUIResources.outcome_generalInfoSection_desc;
			this.detailSectionDescription = AuthoringUIResources.outcome_detailSection_desc;
			this.variabilitySectionDescription = AuthoringUIResources.outcome_variabilitySection_desc;
			this.versionSectionDescription = AuthoringUIResources.outcome_versionInfoSection_desc;
			this.notationSectionDescription = AuthoringUIResources.outcome_notationSection_desc;
			this.tailoringSectionDescription = AuthoringUIResources.outcome_tailoringSection_desc;
			this.iconSectionDescription = AuthoringUIResources.outcome_iconSection_desc;
		}
		if(contentElement instanceof Deliverable){
			this.generalSectionDescription = AuthoringUIResources.deliverable_generalInfoSection_desc;
			this.detailSectionDescription = AuthoringUIResources.deliverable_detailSection_desc;
			this.variabilitySectionDescription = AuthoringUIResources.deliverable_variabilitySection_desc;
			this.versionSectionDescription = AuthoringUIResources.deliverable_versionInfoSection_desc;
			this.notationSectionDescription = AuthoringUIResources.deliverable_notationSection_desc;
			this.tailoringSectionDescription = AuthoringUIResources.deliverable_tailoringSection_desc;
			this.iconSectionDescription = AuthoringUIResources.deliverable_iconSection_desc;
		}
	}

}
