/*
 * Copyright 2006 Maskat Project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.maskat.ide.view;

import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.properties.PropertySheetEntry;
import org.eclipse.ui.views.properties.PropertySheetPage;
import org.maskat.framework.eventdef.Param;
import org.maskat.framework.eventdef.Result;
import org.maskat.framework.screendef.GridHeaderDef;
import org.maskat.framework.screendef.IComponentDef;
import org.maskat.ide.editors.MaskatEditor;
import org.maskat.ide.property.PropertySourceProviderForEditPart;

public class MaskatEditView extends ViewPart implements ISelectionListener {
	MaskatEditViewContent vc;

	Composite parent;

	/** 編集対象MaskatEditor */
	private MaskatEditor editTarget;

	public MaskatEditor getEditTarget() {
		return editTarget;
	}

	protected class SelectionProvider implements ISelectionProvider {

		private ISelection selection;

		public void addSelectionChangedListener(ISelectionChangedListener listener) {
		}

		public ISelection getSelection() {
			return selection;
		}

		public void removeSelectionChangedListener(ISelectionChangedListener listener) {
		}

		public void setSelection(ISelection selection) {
			this.selection = selection;
		}

	}

	/*
	 * (non-Javadoc) Method declared on IViewPart.
	 */
	public void init(IViewSite site) throws PartInitException {
		site.getPage().addSelectionListener(this);
		site.setSelectionProvider(new SelectionProvider());
		super.init(site);
	}

	public void createPartControl(Composite parent) {
		this.parent = parent;
		vc = new MaskatEditViewContent();
		vc.setTheView(this);
		vc.createPartControl(parent);
	}

	public void showParam(Param param, MaskatEditor ep) {
		if (this.editTarget != null && this.editTarget != ep)
			this.editTarget.editMode = MaskatEditor.SCREEN_EDIT_MODE;
		this.editTarget = ep;
		if (vc != null) {
			boolean changed = vc.showParam(parent, param, (CommandStack) ep
					.getAdapter(CommandStack.class));
			if (changed)
				setRootEntry();
		}
		parent.layout();
		this.getSite().getSelectionProvider().setSelection(
				editTarget.getLastSelectionForEdit());
	}

	public void showResult(Result result, MaskatEditor ep) {
		if (this.editTarget != null && this.editTarget != ep)
			this.editTarget.editMode = MaskatEditor.SCREEN_EDIT_MODE;
		this.editTarget = ep;
		if (vc != null) {
			boolean changed = vc.showResult(parent, result, (CommandStack) ep
					.getAdapter(CommandStack.class));
			if (changed)
				setRootEntry();
		}
		parent.layout();
		this.getSite().getSelectionProvider().setSelection(
				editTarget.getLastSelectionForEdit());
		setRootEntry();
	}

	public void setFocus() {
		parent.forceFocus();
	}

	/**
	 * selectionChanged方式ではなく、直接データをこのビューに投げられるインタフェース
	 * 
	 * @param data
	 */
	public void acceptData(String data) {
		vc.acceptData(data);
	}

	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		if (vc == null || vc.isBlankState()) {
			return;
		}
		if (part instanceof MaskatEditor) {
			MaskatEditor maskatEditor = (MaskatEditor) part;

			if (maskatEditor.gettingFocus) {
				maskatEditor.gettingFocus = false;
				return;// selection event will come again. ignore the first
				// time.
			}

			if (maskatEditor.editMode != MaskatEditor.SCREEN_EDIT_MODE) {
				// sourceまたはparamのedit modeだから、selectionを画面上に反映。
				if (!selection.isEmpty()) {
					if (selection instanceof StructuredSelection) {
						StructuredSelection ss = (StructuredSelection) selection;
						if (ss.getFirstElement() instanceof AbstractGraphicalEditPart) {
							AbstractGraphicalEditPart ssG = (AbstractGraphicalEditPart) ss
									.getFirstElement();
							// if (ssG instanceof ComponentEditPart) {
							// Figure parent = ((ComponentEditPart) ssG)
							// .getLabel();
							// for (Iterator it = parent.getChildren()
							// .iterator(); it.hasNext();) {
							// ((Figure) it.next()).setVisible(false);
							// }
							// }
							Object model = ssG.getModel();
							if (model instanceof IComponentDef) {
								IComponentDef cm = (IComponentDef) model;
								vc.acceptData(cm.getName());
								// text.append(cm.getName() + "\n");
							}
							if (model instanceof GridHeaderDef) {
								GridHeaderDef gh = (GridHeaderDef) model;
								vc.acceptData(String.valueOf(gh.idxInParent()));
							}
						}
					}
				}
			}
		}
	}

	/**
	 * MaskatEditorは違ったら、PageのrootEntryも別々にしないといけません。(CommandStackのせい)
	 * pageはこのMaskatEditViewと対応するPropertySheetPage
	 */
	private PropertySheetPage page;

	private void setRootEntry() {
		if (page == null)
			return;// page may have not been initiated.

		PropertySheetEntry entry = new UndoablePropertySheetEntry(vc.getCS());
		entry.setPropertySourceProvider(PropertySourceProviderForEditPart.ins);
		page.setRootEntry(entry);
	}

	public Object getAdapter(Class adapter) {
		if (org.eclipse.ui.views.properties.IPropertySheetPage.class.equals(adapter)) {
			if (vc.getCS() == null)
				return null;

			page = new MaskatPropertySheetPage();
			setRootEntry();

			return page;
		}
		return super.getAdapter(adapter);
	}
}