/*
 * Delivered to the U.S. Government in Accordance with Contract FA8650-10-C-7080.
 *
 * EXPORT CONTROLLED
 * ECCN#   EAR99
 * Warning:  This document contains technical data which is controlled under the
 * Bureau of Industry & Security's Export Administration Regulations and may not be
 * exported or re-exported without authorization by the Bureau of Industry & Security.
 * Diversion contrary to US law is prohibited.
 *
 * (c) 2011 United Technologies Corp.
 * Developed with the sponsorship of the Defense Advanced Research Projects Agency (DARPA).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this data,
 * including any software or models in source or binary form, as well as any drawings, 
 * specifications, and documentation (collectively "the Data"), to deal in the Data without 
 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Data, and to permit persons to whom the Data
 * 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 Data.
 *
 * THE DATA 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, SPONSORS, DEVELOPERS, CONTRIBUTORS, 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 DATA OR THE
 * USE OR OTHER DEALINGS IN THE DATA.
 */

package meta.model.ampl;

import java.io.FileOutputStream;
import java.rmi.Naming;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import meta.ampl.runner.Variable;
import meta.model.Architecture;
import meta.model.Device;
import meta.model.Flow;
import meta.model.Link;
 

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;


public class AMPLresults {
   private 	Map<String,Variable> map;
   private Map<String,String> devMap = new HashMap<String,String>();
   private Architecture arch;
   public AMPLresults(Architecture arch, Map<String,Variable> map) 	{
	  this.arch = arch;
	  this.map = map; 
   }
   private String getCost(String id) {
	   String scost = String.format("cost%s", id);
	   String cost = "0.0";
	   Variable varCost = map.get(scost); 
	   if ( varCost != null) {
		   cost = varCost.value();
	   }
	   return cost;
   }
   private Element doCoreXML(Device device) {
	   String devid = device.getIndexAsString();
	   String cost = getCost(devid);    
	   Variable w = map.get("aircraftweight");
	   Variable totalfuel = map.get("total_fuel");
	   Variable min = map.get("M_in");
	   Variable tsfc = map.get("TSFC");
	   Variable fn = map.get("Thrust_Takeoff_Req");
	   Variable ne = map.get("NumEngines");
	   Variable bpr = map.get("BPR");
	   Variable mcore = map.get("m_core");
	   Variable opr = map.get("OPR");
	   Variable effComp = map.get("IsentropicEfficiency_compressor");
	   Variable effTurb = map.get("Efficiency_turbine");
	   Variable toOut = map.get("To_out_combustor");
 	   toOut.rename("TurbineInletTemperature");
	   Element eDevice = new Element("device");
	    
	   String dn = device.getName();
	   eDevice.setAttribute("id",devid);
	   eDevice.setAttribute("name",dn);
	   eDevice.addContent(w.toElement()); // aircraftweight
	   eDevice.addContent(totalfuel.toElement()) ; 
	   eDevice.addContent(min.toElement());
	   eDevice.addContent(tsfc.toElement());
	   Element eCost = new Element("var");
	   eCost.setAttribute("name","cost");
	   eCost.setAttribute("value",cost);
	   eCost.setAttribute("type","real");
	   eDevice.addContent(eCost);
	   eDevice.addContent(fn.toElement()); // Thrust_Takeoff_Req
	   eDevice.addContent(ne.toElement());
	   eDevice.addContent(mcore.toElement()); 
	   eDevice.addContent(bpr.toElement());
	   eDevice.addContent(opr.toElement()) ;
	   eDevice.addContent(effComp.toElement()); // IsentropicEfficiency_compressor
	   eDevice.addContent(effTurb.toElement());
 	   eDevice.addContent(toOut.toElement()) ; 
	   
	   
	   Element engType = new Element("var");
	   engType.setAttribute("name","engine_type");
	   engType.setAttribute("value",arch.getEngineType());
	   eDevice.addContent(engType);
	   
	   return eDevice;
   }

   private Element doComponentXML(Device device) {
	   Element eDevice = new Element("device");
	   String id = device.getIndexAsString();
	   String dn = device.getName();;
	   String cost = getCost(id);
	   eDevice.setAttribute("id",id);
	   eDevice.setAttribute("name",dn);
	   Element eCost = new Element("var");
	   eCost.setAttribute("name","cost");
	   eCost.setAttribute("value",cost);
	   eCost.setAttribute("type","real");
	   eDevice.addContent(eCost);
	   return eDevice;
   }  
   public Element outXML() {
	   Element root = new Element("architecture");
	   Document doc = new Document(root);
	   String [] toks = arch.getName().split("_");
	   String id = toks[1];
	   root.setAttribute("id",id);
	   root.setAttribute("platform","engine");
	   root.setAttribute("level","0");
	   
	    
	   List<Device> devices = arch.getDevices();
	   for (Device device : devices) {
		   Element outline;
		   String name = device.getName();
		   if ( name.equals("Core") ) {
			outline =   doCoreXML(device);
		   }
		   else {
			 outline = doComponentXML(device);  
		   }
		   root.addContent(outline) ; 
	   }
	   String a = arch.getName();
	   String name = a.replace("Arch", "AMPLOutput");
	   String[] tokens = name.split("_");
	   name = String.format("%s_NT%s", tokens[0],tokens[1]);
	   String tmp = System.getProperty("java.io.tmpdir");
	   tmp = "."; // write to working directory instead
	   String fn = String.format("%s\\a.%s", tmp, id);
	   String t = String.format("AMPL Results for %s written to %s",a,fn);
	   System.out.println(t);
	      
		  List<Flow> flows = arch.getFlowTable();
			 
			for ( Flow flow : flows) {
				  Element eFlow = flow.toElement();
				  root.addContent(eFlow);
			}	  	   	  
		  
	   List<Link> links = arch.getLinkTable();
		 
		for ( Link link : links) {
			  Element elink = link.toElement();
			  root.addContent(elink);
		}

	    try {
		FileOutputStream out = new FileOutputStream(fn);
		XMLOutputter serializer = new XMLOutputter( Format.getPrettyFormat() );
		serializer.output(doc, out);
		out.flush();
		out.close();  
	//	sendToRepository(root);
		
	    }
	    catch (Exception e) {
	    	e.printStackTrace();
	    }
	    return root;
   }
   private void sendToRepository(Element eArch) throws Exception {
	   
	   Element eReq = new Element("service-request");
	   Document doc = new Document(eReq);
	   eReq.setAttribute("name","StoreArchitectures");
	   Element eArgs = new Element("service-arguments");
	   Element eCompArgs = new Element("composite_argument");
	   eCompArgs.setAttribute("name","engine");
	   eCompArgs.setAttribute("type","architectures");
	   Element clone = (Element) eArch.clone();
	   eCompArgs.addContent(clone);
	   eArgs.addContent(eCompArgs);
	   eReq.addContent(eArgs);
				 
		XMLOutputter serializer = new XMLOutputter( Format.getPrettyFormat() );
		String request = serializer.outputString(doc);
	//	Service service = (Service) Naming.lookup("rmi://localhost/repository");
	//	String xml = service.invoke(request);
	//	System.out.println("Storing into the repository");
	//	System.out.println(xml);
   }
}
