/*
 * 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 aee.csv;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import aee.engine.DeviceTable;
import aee.engine.FlowTable;
import aee.engine.InOutTable;
import aee.engine.RuleTable;
import aee.exception.AeeException;
import aee.util.StringUtils;


/**
 * Base class to write any CSV file
 */
public class CsvWriter {
	private Writer out;
	private String fn;

	/**
	 * Create a CSV writer
	 * @param fn The filename to write
	 * @throws AeeException If unable to write the requested file
	 */
	public CsvWriter(String fn) throws AeeException {
		this.fn  = fn;
		this.out = null;
		
		try {
			out = new FileWriter(fn);
		} catch (IOException ioex) {
			throw new AeeException("Unable to create CSV file \"%s\": %s",
					                    fn, ioex.getMessage());
		}
	}
	
	/**
	 * Write a record to the CSV file
	 * @param record  The record to write. Each element is separated with a comma
	 *                when written to the file
	 * @throws AeeException if any I/O exception
	 */
	public void write(String[] record) throws AeeException {
		try {
			out.write(String.format("%s%n", StringUtils.join(record, ",")));
		} catch (IOException ioex) {
			throw new AeeException(ioex);
		}
	}
	
	/**
	 * Report the CSV filename
	 * @return the filename
	 */
	public String getFn() {
		return fn;
	}
	
	/**
	 * Close the file writer
	 */
	public void close() {
		if (out != null)
			try { out.close(); } catch (IOException e) { }
		out = null;
	}
	
	/**
	 * Unit test reads an XML file to create all objects, then writes all CSV files
	 * @param args Unused
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		File   xmlfile  = new File("h:\\Darpa\\Repository\\ENGINE\\PLATFORM\\L1\\p.xml");
		try {
			
			// Define a SAX builder with optional XSD schema validation
			SAXBuilder builder = new SAXBuilder();
			builder.setFeature( "http://apache.org/xml/features/validation/schema", false);
			
			// Parse the platform XML document
			DeviceTable deviceTable = null;
			FlowTable   flowTable   = null;
			InOutTable  inputTable  = null;
			InOutTable  outputTable = null;
			RuleTable   deviceRules = null;
			RuleTable   flowRules   = null;
			
			Document      document = builder.build(xmlfile);
			Element       root     = document.getRootElement();
			Attribute     attr     = root.getAttribute("level");
			if (attr == null)
				throw new AeeException("Is this a platform? There is no level attribute");
			int level = attr.getIntValue();
			
			List<Element> compargs = root.getChildren("composite_argument");
			for (Element comparg : compargs) {
				String  type     = comparg.getAttributeValue("type");
				Element compRoot = (Element) comparg.getChildren().get(0);
				if (type.equalsIgnoreCase("devicetable")) {
					deviceTable = new DeviceTable(level, compRoot);
					
				} else if (type.equalsIgnoreCase("flowtable")) {
					flowTable = new FlowTable(level, compRoot);
					
				} else if (type.equalsIgnoreCase("inputtable")) {
					inputTable = new InOutTable(compRoot, type);
					
				} else if (type.equalsIgnoreCase("outputtable")) {
					outputTable = new InOutTable(compRoot, type);
								
				} else if (type.equalsIgnoreCase("devicerules")) {
					deviceRules = new RuleTable(level, compRoot, type);
					
				} else if (type.equalsIgnoreCase("flowrules")) {
					flowRules = new RuleTable(level, compRoot, type);
				}
			}
			
			// Write the CSV files
			DeviceTableCsvWriter dt = new DeviceTableCsvWriter("t:\\temp\\JB\\devicetable.csv");
			try {
				dt.write(deviceTable);
			} finally {
				dt.close();
			}
			FlowTableCsvWriter ft = new FlowTableCsvWriter("t:\\temp\\JB\\flowtable.csv");
			try {
				ft.write(flowTable);
			} finally {
				ft.close();
			}
			InOutTableCsvWriter iot = new InOutTableCsvWriter("t:\\temp\\JB\\inputtable.csv");
			try {
				iot.write(inputTable, deviceTable, flowTable);
			} finally {
				iot.close();
			}
			iot = new InOutTableCsvWriter("t:\\temp\\JB\\outputtable.csv");
			try {
				iot.write(outputTable, deviceTable, flowTable);
			} finally {
				iot.close();
			}
			DeviceRulesCsvWriter dr = new DeviceRulesCsvWriter("t:\\temp\\JB\\devicerules.csv");
			try {
				dr.write(deviceRules);
			} finally {
				dr.close();
			}
			if (flowRules != null) {
				FlowRulesCsvWriter fr = new FlowRulesCsvWriter("t:\\temp\\JB\\flowrules.csv");
				try {
					fr.write(flowRules);
				} finally {
					fr.close();
				}
			}
			
		} catch (JDOMException jdex) {
			jdex.printStackTrace();
		} catch (IOException ioex) {
			ioex.printStackTrace();
		} catch (AeeException aeex) {
			aeex.printStackTrace();
		}
	}
}
