/*
 * 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.views.properties.tabbed.treenodewrapper;

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

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;

import org.maskat.core.MaskatElement;
import org.maskat.core.event.Event;
import org.maskat.core.event.Result;
import org.maskat.core.event.Target;
import org.maskat.ui.Messages;
import org.maskat.ui.views.properties.tabbed.beanwrapper.LocalDataBinding;
import org.maskat.ui.views.properties.tabbed.beanwrapper.ResultTreeNode;
import org.maskat.ui.views.properties.tabbed.command.AddTreeNodeCommand;
import org.maskat.ui.views.properties.tabbed.masterdetails.EventPropertiesMasterDetailsBlock;

public class LocalDataBindingTreeNode extends AbstractTreeNode {
	private static final String LOCALDATA_BINDING =
		Messages.getString("localDataBindingTreeNode.localDataBinding"); //$NON-NLS-1$		

	private static final String ADD_LOCALDATABINDING =
		Messages.getString("localDataBindingTreeNode.addLocalDataBinding"); //$NON-NLS-1$
	
	public LocalDataBindingTreeNode(Event event) {
		super(event);
	}

	public Object[] getLocalDatabinding() {
		Event event = (Event)maskatElement;
		ArrayList arrayList = null;

		Result result;

		result = event.getResult();

		if (event.getType().equals("remote")) {
						
			if (result != null) {
				Iterator iterator = result.getTypedChildren(Target.class);

				if (iterator != null)
				{
					arrayList = new ArrayList();
					
					while (iterator.hasNext()) {
						MaskatElement basicDef = (MaskatElement) iterator.next();
	
						if (basicDef instanceof Target) {
							if (((Target) basicDef).getType().equals("local")) {
								arrayList.add(new LocalDataBinding((Target) basicDef));
							}
						}
					}
				}
			}
		} else if (event.getType().equals("local")) {
			
			if (result != null) 
			{
				Iterator iterator = result.getTypedChildren(Target.class);

				if (iterator != null)
				{
					if (arrayList == null)
					{
						arrayList = new ArrayList();
					}
					
					while (iterator.hasNext()) {
	
						arrayList.add(new LocalDataBinding((Target) iterator.next()));
	
					}
				}
			}
		}

		if (arrayList != null)
		{
			return arrayList.toArray();
		}
		else
		{
			return null;
		}
	}

	protected void loadChildren() {
		if (((Event)maskatElement).getTypedChildren(Result.class) == null) {
			return;
		}
			
		Result result = ((Event)maskatElement).getResult();
		if (((Event)maskatElement).getType().equals("remote")) {
			if (result != null) {
				Iterator iterator = result.getTypedChildren(Target.class);
				while (iterator != null && iterator.hasNext()) {
					Target target = (Target) iterator.next();
					if (target.getType().equals("local")) {
						addChild(new LocalDataBinding(target));
					}
				}
			}
		} else if (((Event)maskatElement).getType().equals("local")) {
			if (result != null) {
				Iterator iterator = result.getTypedChildren(Target.class);
				while (iterator != null && iterator.hasNext()) {
					addChild(new LocalDataBinding((Target) iterator.next()));
				}
			}
		}
	}
	
	/**destroy the Target bean and Result bean when the child was removed*/
	public void removeChild(ITreeNode child) {
		super.removeChild(child);
		//destroy the Target bean and Result bean
		Target target = (Target)child.getModel();
		Result result = (Result)target.getParent();
		result.removeChild(target);
		if (result.getTypedChildren(Target.class) == null
			&& "local".equals(((Event)maskatElement).getType())) {
			maskatElement.removeChild(result);
		} else if(result.getTypedChildren(Target.class) == null
				&& EventPropertiesMasterDetailsBlock.getTreeNode(result, ResultTreeNode.class) == null) {
			maskatElement.removeChild(result);			
		}
	}
	
	/**add the model relation when add child*/
	public void addChild(ITreeNode child) {
		super.addChild(child);
		Result result = ((Event)maskatElement).getResult();
		if (result == null) {
			result = new Result();
			result.addChild(child.getModel());
			maskatElement.addChild(result);
		}else{
			result.addChild(child.getModel());
		}
		result.setEnable(true);
	}

	public String getDisplayText() {
		return LOCALDATA_BINDING;
	}
	
	public boolean isDeletable() {
		return false;
	}
	
	public IMenuManager fillContextMenu(final TreeViewer treeViewer, IMenuManager manager) {
		final ITreeNode node = this;
		manager.add(new Action(ADD_LOCALDATABINDING){
			public void run() {
				
				Target target = new Target();
				target.setType("local");
//				target.setIn("");
//				target.setOut("");
//				target.setWorkType("");
							
				ITreeNode childNode = new LocalDataBinding(target);
				EventPropertiesMasterDetailsBlock.executeCommand(new AddTreeNodeCommand(treeViewer,node,childNode));

				if ("remote".equalsIgnoreCase(((Event)maskatElement).getType())) {
					//we need to add Result to MessageToBeReceived
					ITreeNode messageReceive = findMessageReceiveTreeNode();
					if (messageReceive != null) {
						//add the result node if it was not added
						if (messageReceive.getChildren().length == 0) {
							EventPropertiesMasterDetailsBlock.executeCommand(new AddTreeNodeCommand(
									treeViewer,messageReceive,new ResultTreeNode((Result)target.getParent())));
							treeViewer.setSelection(new StructuredSelection(childNode), true);
							treeViewer.update(childNode, null);
						}
					}
				}
			}
		});
		return super.fillContextMenu(treeViewer, manager);
	}
	
	private ITreeNode findMessageReceiveTreeNode() {
		ITreeNode root = getParent().getParent();
		Object[] rootChildren = root.getChildren();
		for (int i=0; i<rootChildren.length; i++) {
			if (rootChildren[i] instanceof MessageToBeReceivedTreeNode) {
				return (ITreeNode)rootChildren[i];
			}
		}
		return null;
	}
}
