package comparingDevices;

import icsTables.XMlXSLTClass;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Represents a device
 * @author MC
 *
 */
public class Device {
	public Vector<MOC> vectMOC;
	public Device()
	{
		vectMOC = new Vector<MOC>();
	}
	public Device(File xmlFile)
	{
		vectMOC = new Vector<MOC>();
		if(isXmlFileValid())
			buildDevice(xmlFile);
		else
		{
			//error => throw exception
		}
	}
	public void addMOC(MOC moc)
	{
		vectMOC.add(moc);
	}
	public void addListMOC(List<MOC> list){
		vectMOC.addAll(list);
	}
	public boolean isXmlFileValid()
	{
		boolean result = true;
		// test file
		return result;
	}
	public void parseNode(Node root)
	{
		MOC mocObj = null;
		Attribute attrObj;
		Behavior behavObj;
		Notification notifObj;
		String name = "";
		
		if (root.hasChildNodes()){
	         NodeList children;                
	         int numChildren;
	         Node node;
	         children = root.getChildNodes();
	         numChildren = children.getLength();
	         for (int j=0; j < numChildren; j++) {
	        	 node = children.item(j);                 
		         if (node != null) {                     
		 	          if (node.getNodeType() == Node.ELEMENT_NODE) {
		 	        	  // MOC object name
		 	        	 if (node.getNodeName().equals("OBJECT_NAME")) {
		 	        		  name = node.getFirstChild().getNodeValue();
		 	        		 if(node.getAttributes().getNamedItem("Label").getFirstChild() != null)
		 	        			 name += ":"+node.getAttributes().getNamedItem("Label").getFirstChild().getNodeValue();
			             }
		 	        	 else if (node.getNodeName().equals("OBJECT_ID")) {
		 	        		  name += ":"+ node.getFirstChild().getNodeValue();
		 	        		 mocObj = new MOC(name);
		 	        		  vectMOC.add(mocObj);
		 	        		  name = "";
			             }
		 	        	 
		 	        	  // MOC attributes
			             else if (node.getNodeName().equals("Attribute_Info")) {
			            	NodeList attrAChildren = node.getChildNodes();
                            for (int a = 0; a < attrAChildren.getLength(); a++) {
                            	if (attrAChildren.item(a).getNodeName().equals("Private-Attributes")){
                              		NodeList attrPrivate = attrAChildren.item(a).getChildNodes();
                              		for (int k = 0; k < attrPrivate.getLength(); k++) {
                              			NodeList attrPrivateChild = attrPrivate.item(k).getChildNodes();
                              			for (int p = 0; p < attrPrivateChild.getLength(); p++) {
	  	                                    if (attrPrivateChild.item(p).getNodeName().equals("ATTRIBUTE_NAME")) {
	                                    		attrObj = new Attribute(attrPrivateChild.item(p).getFirstChild().getNodeValue());
	                                    		attrObj.isPrivate = true;
	                                    		mocObj.addAttribute(attrObj);
	                                    	}
                              			}
                               	   	}
                              	}
                               NodeList attrChildren = attrAChildren.item(a).getChildNodes();
                               if (attrAChildren.item(a) != null) {
                                  if (attrAChildren.item(a).getNodeType() == Node.ELEMENT_NODE) {
                               	   	for (int k = 0; k < attrChildren.getLength(); k++) {
  	                                    if (attrChildren.item(k).getNodeName().equals("ATTRIBUTE_NAME")) {
                                    		attrObj = new Attribute(attrChildren.item(k).getFirstChild().getNodeValue());
                                    		mocObj.addAttribute(attrObj);
                                    	}
                               	   }
                                  }
                               }
                            }
			             }
		 	        	  // MOC behaviours
			             else if (node.getNodeName().equals("Behaviour_Info"))
			             {
			            	 NodeList attrAChildren = node.getChildNodes();
	                            for (int a = 0; a < attrAChildren.getLength(); a++) {
	                            	
	                            	if (attrAChildren.item(a).getNodeType() == Node.ELEMENT_NODE && attrAChildren.item(a).getNodeName().equals("Private-Behaviour")){
	                              		NodeList attrPrivate = attrAChildren.item(a).getChildNodes();
	                              		for (int k = 0; k < attrPrivate.getLength(); k++) {
	                              			NodeList attrPrivateChild = attrPrivate.item(k).getChildNodes();
	                              			for (int p = 0; p < attrPrivateChild.getLength(); p++) {
		  	                                    if (attrPrivateChild.item(p).getNodeName().equals("METHOD_NAME")) {
		                                    		behavObj = new Behavior(attrPrivateChild.item(p).getFirstChild().getNodeValue());
		                                    		behavObj.isPrivate = true;
		                                    		mocObj.addBehavior(behavObj);
		                                    	}
	                              			}
	                               	   	}
	                              	}
	                            	else{
		                               NodeList attrChildren = attrAChildren.item(a).getChildNodes();
		                               if (attrAChildren.item(a) != null) {
		                                  if (attrAChildren.item(a).getNodeType() == Node.ELEMENT_NODE) {
		                               	   	for (int k = 0; k < attrChildren.getLength(); k++) {
		  	                                    if (attrChildren.item(k).getNodeName().equals("METHOD_NAME")) {
		                                    		behavObj = new Behavior(attrChildren.item(k).getFirstChild().getNodeValue());
		                                    		mocObj.addBehavior(behavObj);
		                                    	}
		                               	    }
		                                  }
		                               }
	                            	}
	                            }
			             }
		 	        	  // MOC notfications
			             else if(node.getNodeName().equals("Notification_Info"))
			             {
			            	 NodeList attrAChildren = node.getChildNodes();
	                            for (int a = 0; a < attrAChildren.getLength(); a++) {
	                            	if (attrAChildren.item(a).getNodeName().equals("Private-Notification")){
	                              		NodeList attrPrivate = attrAChildren.item(a).getChildNodes();
	                              		for (int k = 0; k < attrPrivate.getLength(); k++) {
	                              			NodeList attrPrivateChild = attrPrivate.item(k).getChildNodes();
	                              			for (int p = 0; p < attrPrivateChild.getLength(); p++) {
		  	                                    if (attrPrivateChild.item(p).getNodeName().equals("NOTIFICATION_NAME")) {
		                                    		notifObj = new Notification(attrPrivateChild.item(p).getFirstChild().getNodeValue());
		                                    		notifObj.isPrivate = true;
		                                    		mocObj.addNotification(notifObj);
		                                    	}
	                              			}
	                               	   	}
	                              	}
	                               NodeList attrChildren = attrAChildren.item(a).getChildNodes();
	                               if (attrAChildren.item(a) != null) {
	                                  if (attrAChildren.item(a).getNodeType() == Node.ELEMENT_NODE) {
	                               	   	for (int k = 0; k < attrChildren.getLength(); k++) {
	  	                                    if (attrChildren.item(k).getNodeName().equals("NOTIFICATION_NAME")) {
	                                    		notifObj = new Notification(attrChildren.item(k).getFirstChild().getNodeValue());
	                                    		mocObj.addNotification(notifObj);
	                                    	}
	                               	   }
	                                  }
	                               }
	                            }
			             }
			             else
			             {
			            	 parseNode(node);
			             }
		 	          }
		         }
	         }
	      }		
	}
	public void buildDevice(File xmlFile)
	{
		//parse xml file
		XMlXSLTClass xmlClass = new XMlXSLTClass();
		Document doc = xmlClass.readXMLFile(xmlFile.getAbsolutePath());
		Node root = doc.getDocumentElement();
		parseNode(root);		
	}
	
	public boolean isImplemented(MOC mocObj)
	{
		boolean found = false;
		int i = 0;
		while(!found && i<vectMOC.size())
		{
			MOC mocObj2 = (MOC)vectMOC.get(i);
			if(mocObj2.compareTo(mocObj) == 0)
				found = true;
			else
				i++;
		}
		return found;		
	}
	public void sortMOC()
	{
                Collections.sort(vectMOC);
		//we remove doublons
		for(int i=1; i<vectMOC.size(); i++){
			MOC objPrec = (MOC)vectMOC.get(i - 1);
			MOC obj = (MOC)vectMOC.get(i);
			if(obj.compareTo(objPrec) == 0)
			{
				objPrec.addToOwners(obj);
				vectMOC.remove(i);
				i--;
			}
		}
	}
	
	public void setOwner(int index)
	{
		for(int i=0; i<vectMOC.size(); i++){
			MOC mocObj = (MOC) vectMOC.get(i);
			mocObj.setOwner(new Integer(index));
		}
	}
	public int getMOC(MOC mocObj){
		boolean found = false;
		int i = 0;
		while(!found && i<vectMOC.size()){
			MOC mocObj2 = (MOC) vectMOC.get(i);
			if( mocObj.compareTo(mocObj2) == 0 )
				found = true;
			else
				i++;
		}
		if (found)
			return i;
		else
			return -1;
				
	}	
}
