//------------------------------------------------------------------------------
// 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.library.tester.impl.testcommands;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.library.tester.TesterOutputUtil;
import org.eclipse.epf.library.tester.iface.TCExeReply;
import org.eclipse.epf.library.tester.iface.TestCommand;
import org.eclipse.epf.library.tester.impl.TestCommandImpl;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * A test command class
 * 
 * @author Weiping Lu
 * @since 1.0
 * 
 */
public abstract class TCEditMethodElementBase extends TestCommandImpl {					
	
	static class TagData {
		public Map attMap = new LinkedHashMap();
		public Map refMap = new LinkedHashMap();
	}
	
	Element element;
	private EClass eclass;
	private TagData tagData;
	private MethodElement methodElement;
	private Map refValueMap = new HashMap();
	private static Map eclassDataMap = new HashMap();
	private List childCommands = new ArrayList();
	private boolean isChildCommand = false;
	
	protected TestCommand newChildCommand(Class type) {
		try {
			TCEditMethodElementBase command = (TCEditMethodElementBase) type.newInstance();
			command.setOwner(getOwner());
			command.setIsChildCommand(true);
			if (localDebug) {
				System.out.println("LD> newChildCommand: " + type);
			}
			return command;
		} catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	public void parse(Element element) {
		init(element);
		parseAttributes();		
		parseValueChildren();
	}
	
	private void init(Element element) {
		this.element = element;
		String type = element.getAttribute(AT_Type);
		eclass = methodElement == null ? getEClass(type) : methodElement.eClass();
		if (eclass == null) {
			return;
		}
		tagData = (TagData) eclassDataMap.get(eclass);
		if (tagData != null) {
			return;
		}		
		tagData = new TagData();
		eclassDataMap.put(eclass, tagData);
		
		if (localDebug) {
			System.out.println("LD> eclass: " + eclass.getName());
			TesterOutputUtil.show("eclass.getEAllAttributes()", eclass.getEAllAttributes());
			TesterOutputUtil.show("eclass.getEAllReferences()", eclass.getEAllReferences());
		}
		
		addToEclassDataMap(eclass.getEAllAttributes(), tagData.attMap);
		addToEclassDataMap(eclass.getEAllReferences(), tagData.refMap);
		
	}
	
	private void addToEclassDataMap(List features, Map feaMap) {		
		for (int i=0; i<features.size(); i++) {
			EStructuralFeature feature = (EStructuralFeature) features.get(i);			
			feaMap.put(feature.getName(), feature);
		}
	}
	
	protected void parseAttributes() {
		setAttribute(AT_Type, element.getAttribute(AT_Type));
		setAttribute(AT_Path, element.getAttribute(AT_Path));
		
		for (Iterator it = tagData.attMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			String at_tag = (String) entry.getKey();
			setAttribute(at_tag, element.getAttribute(at_tag));
		}
	}
	
	protected void parseValueChildren() {
		for (Iterator it = tagData.refMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			String childTag = (String) entry.getKey();
			setAttribute(childTag, element.getAttribute(childTag));
			parseChildTagAsValue(childTag);									
		}
	}

	private void parseChildTagAsValue(String childTag) {
		NodeList cnodes = element.getElementsByTagName(childTag);
		if (cnodes == null || cnodes.getLength() == 0) {
			return;
		}
		Element cElement = (Element) cnodes.item(0);
		cnodes = cElement.getElementsByTagName(VT_Value);	
		if (cnodes == null || cnodes.getLength() == 0) {
			return;
		}
		List valueList = new ArrayList();
		for (int i=0; i<cnodes.getLength(); i++) {
			Element vElem = (Element) cnodes.item(i);
			String value = vElem.getFirstChild().getNodeValue();
			valueList.add(value);
		}
		refValueMap.put(childTag, valueList);
	}
	
	private void setMethodElement(MethodElement e) {
		methodElement = e;
	}
	
	protected MethodElement getMethodElement() {
		return methodElement;
	}
	
	public void parsePresentation(Element presentationElement) {
		if ( ! (methodElement instanceof DescribableElement)) {
			return;
		}
		ContentDescription presentation = ((DescribableElement) methodElement).getPresentation();
		if (presentation == null) {
			return;
		}
		TCEditMethodElementBase childCommand = (TCEditMethodElementBase) newChildCommand(TCEditPresentation.class);
		childCommand.setMethodElement(presentation);
		childCommand.parse(presentationElement);
		addToChildCommands(childCommand);
	}	
	
	protected TagData getTagData() {
		return tagData;
	}
	
	private boolean parseChildTagAsCommand(Element cElement, String childTag) {
		if (childTag.equals("presentation")) {
			parsePresentation(cElement);
			return true;
		}
		return false;
	}
	
	private void parseCommandChildren() {
		for (Iterator it = tagData.refMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			String childTag = (String) entry.getKey();
			NodeList cnodes = element.getElementsByTagName(childTag);
			if (cnodes == null || cnodes.getLength() == 0) {
				continue;
			}
			Element cElement = (Element) cnodes.item(0);
			parseChildTagAsCommand(cElement, childTag);									
		}
	}
	
	private TCExeReply executeChildCommands() {
		for (int i=0; i<childCommands.size(); i++) {
			TestCommand command = (TestCommand) childCommands.get(i);
			TCExeReply result = command.execute();
			if (result != null && !result.passing()) {
				return result;
			}
		}
		return null;
	}
	
	public TCExeReply execute() {		
		MethodLibrary currLib = getOwner().getCurrentBaseLib();		
		String path = getAttribute(AT_Path);
		if (methodElement == null) {
			methodElement = (MethodElement) TesterOutputUtil.getMethodElement(currLib, path);
		}
		if (methodElement == null) {
			return null;
		}
		parseCommandChildren();
		
		Map attMap = getTagData().attMap;
		Map attributeMap = getAttributeMap();
		for (Iterator it = attMap.entrySet().iterator(); it.hasNext();) {
			Map.Entry entry = (Map.Entry) it.next();
			String at_tag = (String) entry.getKey();
			EAttribute eatt = (EAttribute) entry.getValue();
			EDataType dataType = eatt.getEAttributeType();
			String at_val = (String) attributeMap.get(at_tag);
			if (localDebug) {
				System.out.println("LD> at_tag: " + at_tag);
				System.out.println("LD> at_val: " + at_val);
				System.out.println("LD> eatt: " + eatt);
				System.out.println("LD> dataType: " + dataType);
				System.out.println("");
			}			
			if (at_val == null || at_val.length() == 0) {
				continue;
			}
			if (dataType.getName().equals("String")) {
				methodElement.eSet(eatt, at_val);
			}
		}
		
		executeChildCommands();
		
		if (! getIsChildCommand()) {
			save((MethodElement) methodElement.eContainer());
		}

		return null;
	}

	protected void setIsChildCommand(boolean b) {
		isChildCommand = b;
	}
	
	protected boolean getIsChildCommand() {
		return isChildCommand;
	}
	
	protected void addToChildCommands(TestCommand command) {
		childCommands.add(command);
	}
}


