/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * 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:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.ui.editors.layout.editparts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.CompoundSnapToHelper;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.SnapToGeometry;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editpolicies.SnapFeedbackPolicy;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.views.properties.tabbed.view.Tab;
import org.eclipse.ui.part.IPage;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.PropertySheet;

import org.maskat.core.layout.Container;
import org.maskat.core.layout.Component;
import org.maskat.core.layout.StructuredComponent;
import org.maskat.ui.editors.layout.commands.AddComponentCommand;
import org.maskat.ui.editors.layout.commands.ChangeConstraintCommand;
import org.maskat.ui.editors.layout.editpolicies.ComponentXYLayoutEditPolicy;
import org.maskat.ui.editors.layout.editpolicies.DataBindingEditPolicy;
import org.maskat.ui.editors.layout.editpolicies.FeedBackComponentEditPolicy;
import org.maskat.ui.editors.layout.editpolicies.LabelDirectEditPolicy;
import org.maskat.ui.editors.layout.editpolicies.MaskatComponentEditPolicy;
import org.maskat.ui.editors.layout.figures.TextFigure;
import org.maskat.ui.editors.layout.tools.TextCellEditorLocator;
import org.maskat.ui.editors.layout.tools.TextDirectEditManager;
import org.maskat.ui.views.properties.AbstractComponentPropertySource;
import org.maskat.ui.views.properties.DynaBeanPropertySource;
import org.maskat.ui.views.properties.LayoutPropertySource;
import org.maskat.ui.views.properties.advanced.AdvancedPropertySheetSection;
import org.maskat.ui.views.properties.tabbed.TabbedEventPropertySheetPage;

public class ComponentEditPart extends AbstractGraphicalEditPart
	implements PropertyChangeListener, IdDirectEditable {

	protected IFigure createFigure() {
		return new TextFigure("");
	}

	protected void createEditPolicies() {
		int style = FeedBackComponentEditPolicy.getStyle(this);
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new MaskatComponentEditPolicy());
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new ComponentXYLayoutEditPolicy(style));
		installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new LabelDirectEditPolicy());
		installEditPolicy("Snap Feedback", new SnapFeedbackPolicy());
		installEditPolicy(DataBindingEditPolicy.ROLE, new DataBindingEditPolicy());
	}
	
	public void activate() {
		super.activate();
		if (getModel() instanceof Component) {
			((Component) getModel()).addPropertyChangeListener(this);
		}
	}

	public void deactivate() {
		if (getModel() instanceof Component) {
			((Component) getModel()).removePropertyChangeListener(this);
		}
		super.deactivate();
	}

	public void propertyChange(PropertyChangeEvent evt) {
		refreshVisuals();
		refreshAdvancedPropertySheet();
	}	
	
	protected void refreshVisuals() {
		Component comp = (Component) getModel();
		Rectangle constraint = new Rectangle(comp.getLeft(), comp.getTop(), comp.getWidth(),
				comp.getHeight());
		((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), constraint);
	}
	
	protected void refreshAdvancedPropertySheet() {
		IWorkbench workbench = PlatformUI.getWorkbench();
		IWorkbenchPage page = workbench.getActiveWorkbenchWindow().getActivePage();
		if (page == null) {
			return;
		}
		
		IViewPart vp = page.findView(IPageLayout.ID_PROP_SHEET); 
		if (vp == null) {
			return;
		}

		PropertySheet ps = (PropertySheet)vp;
		IPage cp = ps.getCurrentPage();
		if (cp != null && cp instanceof TabbedEventPropertySheetPage) {
			TabbedEventPropertySheetPage viewer = (TabbedEventPropertySheetPage)cp;
			Tab tab = viewer.getCurrentTab();
			for (int i=0; tab!= null && i<tab.getSections().length; i++) {
				if (tab.getSections()[i] instanceof AdvancedPropertySheetSection) {
					try {
						tab.getSections()[i].refresh();
					} catch (Exception e) {
//						e.printStackTrace();
					}
					break;
				}
			}
		}
	}
	
	public Object getAdapter(Class key) {
		if (key.equals(IPropertySource.class)) {
			Object object = Platform.getAdapterManager().getAdapter(getModel(), key);
			if (object instanceof AbstractComponentPropertySource) {
				((AbstractComponentPropertySource)object).setCommandStack(getViewer().getEditDomain().getCommandStack());
			}else if (object instanceof LayoutPropertySource) {
				((LayoutPropertySource)object).setCommandStack(getViewer().getEditDomain().getCommandStack());
			}else if (object instanceof DynaBeanPropertySource) {
				((DynaBeanPropertySource)object).setCommandStack(getViewer().getEditDomain().getCommandStack());
			} 
			return object;
		} else if (key.equals(SnapToHelper.class)) {
			ArrayList list = new ArrayList();
			Object gird = getViewer().getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
			if (gird instanceof Boolean && ((Boolean) gird).booleanValue()) {
				list.add(new SnapToGrid(this));
			}
			Object snap = getViewer().getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED);
			if (snap instanceof Boolean && ((Boolean) snap).booleanValue()) {
				list.add(new SnapToGeometry(this));
			}
			if (list.size() > 0) {
				return new CompoundSnapToHelper(
					(SnapToHelper[]) list.toArray(new SnapToHelper[0]));
			}
		} else if (key.equals(LabelDirectEditable.class) &&
					this instanceof LabelDirectEditable) {
			return this;
		} else if (key.equals(IdDirectEditable.class)) {
			return this;
		} else if (key.isAssignableFrom(getModel().getClass())) {
			return getModel();
		}
		return super.getAdapter(key);
	}
	
	public Command createConstrainCommand(Object model, Rectangle constraint) {
		if (model instanceof Component) {
			return  new ChangeConstraintCommand((Component) model, constraint);
		}
		return null;
	}

	public Command getCreateCommand(Object parent, Object node) {
		if (parent instanceof Container || parent instanceof StructuredComponent) {
			return  new AddComponentCommand((Component) parent, (Component) node);
		}
		return null;
	}
	
	public void performRequest(Request req) {
		if (getAdapter(LabelDirectEditable.class) != null) {
			if (REQ_OPEN.equals(req.getType())) {
				new TextDirectEditManager(this, null, 
					new TextCellEditorLocator(getFigure())).show();
		
			}
		}
	}

	public String getId() {
		return ((Component) getModel()).getName();
	}

	public void setId(String id) {
		((Component) getModel()).setName(id);
	}
}

