/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 22-Dec-2004
 *
 */
package uk.ac.ic.doc.kevlar.gui.internal.taskpane.loadpane;

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

import org.eclipse.swt.graphics.Point;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import uk.ac.ic.doc.kevlar.core.framework.IProgramIDDescription;
import uk.ac.ic.doc.kevlar.gui.GUIManager;
import uk.ac.ic.doc.kevlar.gui.internal.layout.ILayoutData;
import uk.ac.ic.doc.kevlar.gui.internal.layout.LayoutData;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.InputNodeEntry;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.OutputNodeEntry;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.Pipe;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.PipeLineManager;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.Program;
import uk.ac.ic.doc.kevlar.hial.IArgumentValuePair;
import uk.ac.ic.doc.kevlar.hial.IGUIContextLoader;
import uk.ac.ic.doc.kevlar.hial.IHialProgram;
import uk.ac.ic.doc.kevlar.hial.IRefObject;
import uk.ac.ic.doc.kevlar.publicInterfaces.INodeID;
import uk.ac.ic.doc.kevlar.publicUtil.collections.Tuple;
import uk.ac.ic.doc.kevlar.publicUtil.dom.XMLUtil;

/**
 * @author Kate
 *
 */
public class GUILoaderCallback implements IGUIContextLoader {

	private static GUILoaderCallback singleton;
	private List<Program> macroPrograms;
	private List<Long> programIDs;
	private List<MacroLoadStructure> macroStructures;
	
	private GUILoaderCallback()
	{
		macroStructures = new ArrayList<MacroLoadStructure>();
	}
	
	public static GUILoaderCallback getSingleton()
	{
		return singleton;
	}
	
	public static void createSingleton()
	{
		if (singleton==null)
		{
			singleton = new GUILoaderCallback();
		}
	}
	
	public void loadGUIContext(Element guiContext) {
		/* load macros */
		
		
		Element macrosElem = XMLUtil.yankElement(guiContext, "macros");
		String macrosTagContent = XMLUtil.getInnerContent(macrosElem);
		
		if (!macrosTagContent.equals(" "))
		{
			NodeList macros = macrosElem.getElementsByTagName("macro"); 
			
			for(Element macro : XMLUtil.getElementIterator(macros)) 
			{	
				Element macroId = XMLUtil.yankElement(macro, "macroId");
				String id = XMLUtil.getInnerContent(macroId);
				MacroLoadStructure loadMacro = new MacroLoadStructure(Integer.parseInt(id));
				
				NodeList layouts = macro.getElementsByTagName("lauout");
				
				Element layoutInfo = XMLUtil.yankElement(macro, "layout");
				
				System.out.println(XMLUtil.getInnerContent(layoutInfo));
				
				int x = Integer.parseInt((XMLUtil.yankText(layoutInfo, "xposition")));
				int y = Integer.parseInt((XMLUtil.yankText(layoutInfo, "yposition")));
				Point position = new Point(x,y);
				
				System.out.println("Loading... MacroId: "+id+" y: "+y);
				int width = Integer.parseInt((XMLUtil.yankText(layoutInfo, "width")));
				int height = Integer.parseInt((XMLUtil.yankText(layoutInfo, "height")));
				Point size = new Point(width, height);
				
				loadMacro.setPosition(position);			
				macroStructures.add(Integer.parseInt(id), loadMacro);
				
				NodeList programs = macro.getElementsByTagName("macro-program");
				
				for (Element program : XMLUtil.getElementIterator(programs))
				{
					System.out.println(XMLUtil.getInnerContent(program));
					String refId = XMLUtil.getInnerContent(program);
					loadMacro.addReference(refId);
				}
				
				NodeList innerMacros = macro.getElementsByTagName("innerMacroId");

				for (Element innerMacro : XMLUtil.getElementIterator(innerMacros))
				{
					String innerMacroId = XMLUtil.getInnerContent(innerMacro);
					int innerId = Integer.parseInt(innerMacroId);
					
					if (innerId!=-1)
					{
						loadMacro.addInnerIds(innerId);
					}
				}
				
			}
		}
			
	}

	public Tuple<IRefObject, IHialProgram> loadGUIProgram(Element guiProgram, IProgramIDDescription description) {
		
		//add program to the PipeLineManager
		//get the layout context from the guiProgram element and set 
		//the layout parameters
		
		Element reference = XMLUtil.yankElement(guiProgram, "refId");
		String refId = XMLUtil.getInnerContent(reference);
		
		Element layoutInfo = XMLUtil.yankElement(guiProgram, "layout");
		
		int x = Integer.parseInt((XMLUtil.yankText(layoutInfo, "xposition")));
		int y = Integer.parseInt((XMLUtil.yankText(layoutInfo, "yposition")));
		Point position = new Point(x,y);
		
		int width = Integer.parseInt((XMLUtil.yankText(layoutInfo, "width")));
		int height = Integer.parseInt((XMLUtil.yankText(layoutInfo, "height")));
		Point size = new Point(width, height);
		
		ILayoutData layoutData = new LayoutData(position, size);
		Program program = PipeLineManager.getSingleton().loadProgram(description, layoutData);
		
		
		for (MacroLoadStructure macroStructure : macroStructures)
		{
			if (macroStructure.getReference().contains(refId))
			{
				macroStructure.addPrograms(program);
			}
		}
		
		/*for (Long programId : programIDs)
		{
			if (program.getProgramIDDescription().getProgramID().getID()==programId.longValue())
			{
				System.out.println("adding macro program to the list");
				macroPrograms.add(program);
			}
		} */
		
		//Get an instance of IHialProgram from the Hial
		IHialProgram ref = GUIManager.getHialContext().getProgram(program);
		
		return new Tuple<IRefObject, IHialProgram>(program, ref);
	}


	public void loadGUIArguments(IRefObject program, Collection<IArgumentValuePair> values) {
		
		for(IArgumentValuePair arg : values)
		{
			((Program)program).addArgument(arg.getArgInfo());
		}
		
		IHialProgram hialProgram = GUIManager.getHialContext().getProgram(program);
		hialProgram.updateArgumentValues(values);
		
	}

	
	public IRefObject loadGUIPipe(Element guiPipe, IRefObject fromProgram, IRefObject toProgram, INodeID fromNodeID, INodeID toNodeID) {
	
		
		OutputNodeEntry outputNode = (OutputNodeEntry)((Program)fromProgram).getNode(fromNodeID);
		InputNodeEntry inputNode = (InputNodeEntry)((Program)toProgram).getNode(toNodeID);
		
		Pipe pipe = PipeLineManager.getSingleton().addPipe(outputNode, inputNode);
		
		return pipe;
	}

	
	public void programNotFound(String programCanonicalName) {
		//some error message must be displayed
	}
	
	public List<MacroLoadStructure> getMacroStructures()
	{
		return macroStructures;
	}
	
	public void clearMacroStructureList()
	{
		macroStructures.clear();
	}

}
