package com.esri.geoevent.solutions.processor.geometry;

/*
 * #%L
 * Esri :: AGES :: Solutions :: Processor :: Geometry
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2013 - 2014 Esri
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.joda.time.DateTime;

import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.LinearUnit;
import com.esri.core.geometry.MapGeometry;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.Polygon;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.geometry.Unit;
import com.esri.core.map.FeatureSet;
import com.esri.core.map.Graphic;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.DefaultFieldDefinition;
import com.esri.ges.core.geoevent.FieldDefinition;
import com.esri.ges.core.geoevent.FieldType;
import com.esri.ges.core.geoevent.GeoEvent;
import com.esri.ges.core.geoevent.GeoEventDefinition;
import com.esri.ges.core.geoevent.GeoEventPropertyName;
import com.esri.ges.datastore.agsconnection.ArcGISServerConnection;
import com.esri.ges.datastore.agsconnection.ArcGISServerType;
import com.esri.ges.datastore.agsconnection.Field;
import com.esri.ges.datastore.agsconnection.Layer;
import com.esri.ges.manager.datastore.agsconnection.ArcGISServerConnectionManager;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.messaging.GeoEventCreator;
import com.esri.ges.messaging.Messaging;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;
import com.esri.ges.spatial.Geometry;
import com.esri.ges.spatial.GeometryException;
import com.esri.ges.spatial.Spatial;

public class QueryReportProcessor extends GeoEventProcessorBase {

	private static final Log LOG = LogFactory.getLog(RangeFanProcessor.class);
	public Spatial spatial;
	public GeoEventDefinitionManager manager;
	public ArcGISServerConnectionManager connectionManager;
	public Messaging messaging;
	private SpatialReference srIn;
	private SpatialReference srBuffer;
	private SpatialReference srOut;
	private ArrayList<Object>queries = new ArrayList<Object>();
	private HashMap<String, Object>responseMap = new HashMap<String, Object>();
	private com.esri.core.geometry.Geometry inGeometry;
	public QueryReportProcessor(GeoEventProcessorDefinition definition, Spatial s, GeoEventDefinitionManager m, ArcGISServerConnectionManager cm, Messaging msg)
			throws ComponentException {
		super(definition);
		spatial = s;
		manager = m;
		connectionManager = cm;
		messaging = msg;
		geoEventMutator= true;
	}
	
	//@Override
	public void onServiceStop()
	{
		definition.getPropertyDefinitions().clear();
		((QueryReportProcessorDefinition)definition).GenerateProperties();
	}
	@Override
	public GeoEvent process(GeoEvent ge) throws Exception {
		//CreateQueryMap();
		CreateQueries();
		double radius = (Double)properties.get("radius").getValue();
		String units = properties.get("units").getValue().toString();
		int inwkid = (Integer) properties.get("wkidin").getValue();
		int outwkid = (Integer) properties.get("wkidout").getValue();
		int bufferwkid = (Integer) properties.get("wkidbuffer").getValue();
		srIn = SpatialReference.create(inwkid);
		srBuffer = SpatialReference.create(bufferwkid);
		srOut = SpatialReference.create(outwkid);

		com.esri.ges.spatial.Geometry geo = ge.getGeometry();
		com.esri.ges.spatial.Geometry inGeo = null;
		if(properties.get("geosrc").getValueAsString().equals("Buffer"))
		{
			inGeometry = constructGeometry(geo);
			Unit u = queryUnit(units);
			inGeo = constructBuffer(geo,radius,u);
		}
		else if(properties.get("geosrc").getValueAsString().equals("Event Definition"))
		{
			
			String eventfld = properties.get("geoeventdef").getValue().toString();
			String[] arr = eventfld.split(":");
			String geostr = (String)ge.getField(arr[1]);
			com.esri.ges.spatial.Geometry g = constructGeometryFromString(geostr);
			com.esri.core.geometry.Geometry polyGeo= constructGeometry(g);
			Envelope env = new Envelope();
			polyGeo.queryEnvelope(env);
			inGeometry = env.getCenter();
			com.esri.core.geometry.Geometry projGeo = GeometryEngine.project(polyGeo, srBuffer, srOut);
			String json = GeometryEngine.geometryToJson(srOut, projGeo);
			inGeo = spatial.fromJson(json);
		}
		else
		{
			
			com.esri.core.geometry.Geometry polyGeo = constructGeometry(geo);
			Envelope env = new Envelope();
			polyGeo.queryEnvelope(env);
			inGeometry = env.getCenter();
			com.esri.core.geometry.Geometry projGeo = GeometryEngine.project(polyGeo, srBuffer, srOut);
			String json = GeometryEngine.geometryToJson(srOut, projGeo);
			inGeo = spatial.fromJson(json);
			
		}
		String jsonGeo =  inGeo.toJson();
		String geotype = GeometryUtility.parseGeometryType(inGeo.getType());
		ExecuteRestQueries(jsonGeo, geotype);
		String timestamp = "";
		if((Boolean)properties.get("usetimestamp").getValue())
	       {
			String eventfld = properties.get("timestamp").getValueAsString();
			String[] arr = eventfld.split(":");
			timestamp = ge.getField(arr[1]).toString();
	       }
		DateTime dt = DateTime.now();
		String ts = ((Integer) dt.getYear()).toString()
				+ ((Integer) dt.getMonthOfYear()).toString()
				+ ((Integer) dt.getDayOfMonth()).toString()
				+ ((Integer) dt.getHourOfDay()).toString()
				+ ((Integer) dt.getMinuteOfHour()).toString()
				+ ((Integer) dt.getSecondOfMinute()).toString();
		String file = properties.get("filename").getValueAsString() + ts + ".html";
	    
		ParseResponses(timestamp, file);
		String host = properties.get("host").getValueAsString();
		if(host.contains("http://"))
		{
			host.replace("http://", "");
		}
		String url = "http://" + host + ":6180/geoevent/assets/reports/" + file;
		GeoEventDefinition geoDef = ge.getGeoEventDefinition();
		String outDefName = geoDef.getName() + "_out";
		GeoEventDefinition edOut;
		if((edOut=manager.searchGeoEventDefinition(outDefName, getId()))==null)
		{
			List<FieldDefinition> fds = Arrays
					.asList(((FieldDefinition) new DefaultFieldDefinition(
							"url", FieldType.String)));
			edOut = geoDef.augment(fds);
			edOut.setOwner(getId());
			edOut.setName(outDefName);
			manager.addGeoEventDefinition(edOut);
		}
		GeoEventCreator geoEventCreator = messaging.createGeoEventCreator();
		GeoEvent geOut = geoEventCreator.create(edOut.getGuid(), new Object[] {
				ge.getAllFields(), url });
		geOut.setProperty(GeoEventPropertyName.TYPE, "message");
		geOut.setProperty(GeoEventPropertyName.OWNER_ID, getId());
		geOut.setProperty(GeoEventPropertyName.OWNER_ID, definition.getUri());

		for (Map.Entry<GeoEventPropertyName, Object> property : ge.getProperties())
	        if (!geOut.hasProperty(property.getKey()))
	          geOut.setProperty(property.getKey(), property.getValue());
		queries.clear();
		responseMap.clear();
		return geOut;

	}
	private Unit queryUnit(String units)
	{
		UnitConverter uc = new UnitConverter();
		String cn = uc.findConnonicalName(units);
		int unitout = uc.findWkid(cn);
		Unit  u = new LinearUnit(unitout);
		return u;
	}
	private com.esri.core.geometry.Geometry constructGeometry(com.esri.ges.spatial.Geometry geo) throws Exception
	{
		try{
			String jsonIn = geo.toJson();
			JsonFactory jf = new JsonFactory();
			JsonParser jp = jf.createJsonParser(jsonIn);
			MapGeometry mgeo = GeometryEngine.jsonToGeometry(jp);
			com.esri.core.geometry.Geometry geoIn= mgeo.getGeometry();
			return GeometryEngine.project(geoIn, srIn, srBuffer);
		}
		catch(Exception e)
		{
			LOG.error(e.getMessage());
			LOG.error(e.getStackTrace());
			throw(e);
		}
	}
	
	private com.esri.ges.spatial.Geometry constructGeometryFromString(String geoString) throws GeometryException
	{
		String[] pairs = geoString.split(" ");
		
		Polygon polygon = new Polygon();
		Boolean firstit = true;
		for(String coords: pairs)
		{
			
			String[] tuple = coords.split(",");
			Double x = Double.parseDouble(tuple[0]);
			Double y = Double.parseDouble(tuple[1]);
			Point p = new Point(x,y);
			Double z = Double.NaN;
			if (tuple.length>2)
			{
				z = Double.parseDouble(tuple[2]);
				p.setZ(z);
			}
			if(firstit)
			{
				polygon.startPath(p);
				firstit=false;
			}
			else
			{
				polygon.lineTo(p);
			}
		}
		polygon.closeAllPaths();
		String json = GeometryEngine.geometryToJson(srIn, polygon);
		return spatial.fromJson(json);
	}
	
	
	private com.esri.ges.spatial.Geometry constructBuffer(Geometry geo, double radius, Unit u) throws GeometryException, JsonParseException, IOException
	{
		
		com.esri.core.geometry.Geometry buffer = GeometryEngine.buffer(inGeometry, srBuffer, radius, u);
		com.esri.core.geometry.Geometry bufferout = GeometryEngine.project(buffer, srBuffer, srOut);
		String json = GeometryEngine.geometryToJson(srOut, bufferout);
		return spatial.fromJson(json);
		
	}
	
	public void CreateQueries()
	{
		String connName = properties.get("connection").getValueAsString();
		ArcGISServerConnection conn = connectionManager.getArcGISServerConnection(connName);
		URL url = conn.getUrl();
		String folder = properties.get("folder").getValueAsString();
		
		String service = properties.get("service").getValueAsString();
		String lyrName = properties.get("layer").getValueAsString();
		Layer layer =conn.getLayer(folder, service, lyrName, ArcGISServerType.FeatureServer);
		String layerId = ((Integer)layer.getId()).toString();
		String field = properties.get("field").getValueAsString();
		
		String baseUrl = url.getProtocol() +"://"+ url.getHost() + ":" + url.getPort()
				+ url.getPath() + "rest/services/";
		String curPath = baseUrl + "/" + folder + "/" + service + "/FeatureServer/" + layerId;
		String restpath = curPath + "/query?";
		HashMap<String, Object> query = new HashMap<String, Object>();
		HashMap<String, String> fieldMap = new HashMap<String, String>();
		String fldsString = field;
		Field[] fields = conn.getFields(folder, service, layer.getId(), ArcGISServerType.FeatureServer);

		Boolean usingDist=false;
		String lyrHeaderCfg = "";
		String distToken="";
		String distUnits="";
		String wc="";
		String itemConfig = "";
		wc = properties.get("wc")
				.getValueAsString();
		lyrHeaderCfg = properties.get("lyrheader").getValueAsString();
		usingDist = (Boolean)properties.get("calcDistance").getValue();
		if(usingDist)
		{
			distToken=properties.get("dist_token").getValueAsString();
			distUnits=properties.get("dist_units").getValueAsString();
		}
		String token = properties.get("field-token")
				.getValueAsString();
		fieldMap.put(field, token);
		itemConfig = properties.get("item-config").getValueAsString();
		query.put("restpath", restpath);
		query.put("path", curPath);
		query.put("whereclause", wc);
		query.put("fields", fldsString );
		query.put("outfields", fields);
		query.put("tokenMap", fieldMap);
		query.put("headerconfig", lyrHeaderCfg);
		query.put("usingdist", usingDist);
		query.put("distunits", distUnits);
		query.put("disttoken", distToken);
		query.put("itemconfig", itemConfig);
		query.put("layer", layer.getName());
		UUID uid = UUID.randomUUID();
		query.put("id", uid);
		queries.add(query);
	}
	public void CreateQueryMap()
	{
		Collection<ArcGISServerConnection> serviceConnections = this.connectionManager
				.getArcGISServerConnections();

		Iterator<ArcGISServerConnection> it = serviceConnections.iterator();
		ArcGISServerConnection conn;
		while (it.hasNext()) {
			conn = it.next();
			
			//String connName = conn.getName();
			String[] folders = conn.getFolders();

			URL url = conn.getUrl();
			
			String baseUrl = url.getProtocol() +"://"+ url.getHost() + ":" + url.getPort()
					+ url.getPath() + "rest/services/";
			//HashMap<String, Object> folderMap = new HashMap<String, Object>();
			for (int i = 0; i < folders.length; ++i) {
				String path = baseUrl + folders[i] + "/";
				String folder = folders[i];
				String[] fservices = conn.getFeatureServices(folder);
				//HashMap<String,Object>serviceMap = new HashMap<String,Object>();
				for (int j = 0; j < fservices.length; ++j) {
					String fs = fservices[j];
					path += fs + "/FeatureServer/";
					String fqService = folder + "_" + fs;
					String pdName = "use_" + fqService;
					pdName=pdName.replace(" ", "_");
					if ((Boolean) properties.get(pdName).getValue()) {
						
						ArrayList<Layer> layers = (ArrayList<Layer>) conn
								.getLayers(folder, fs,
										ArcGISServerType.FeatureServer);
						//HashMap<String, Object> layerMap = new HashMap<String, Object>();
						
						
						for (int k = 0; k < layers.size(); ++k) {
							HashMap<String, Object> query = new HashMap<String, Object>();
							HashMap<String, String> fieldMap = new HashMap<String, String>();
							String fldsString = "";
							Field[] fields = conn.getFields(folder, fs, k, ArcGISServerType.FeatureServer);
							Boolean usingDist=false;
							String curPath="";
							String restpath="";
							String lyrHeaderCfg = "";
							String distToken="";
							String distUnits="";
							String wc="";
							String itemConfig = "";
							String curLyr = layers.get(k).getName();
							String lyrName = fqService + "_"
									+ ((Integer) k).toString();
							lyrName = lyrName.replace(" ", "_");
							if ((Boolean) properties.get(lyrName).getValue()) {
								curPath = path + ((Integer) k).toString();
								restpath = path + ((Integer) k).toString() + "/query?";
								wc = properties.get(lyrName + "_whereclause")
										.getValueAsString();
								lyrHeaderCfg = properties.get(lyrName + "_header").getValueAsString();
								usingDist = (Boolean)properties.get(lyrName + "_calcDistance").getValue();
								if(usingDist)
								{
									distToken=properties.get(lyrName + "_dist_token").getValueAsString();
									distUnits=properties.get(lyrName + "_dist_units").getValueAsString();
								}
								
								
								itemConfig = properties.get(lyrName + "_config").getValueAsString();
								
								Boolean first = true;
								for (int l = 0; l < fields.length; ++l) {
									String fld = fields[l].getName();
									
									String fldPropName = lyrName + fld;
									fldPropName = fldPropName.replace(" ", "_");
									
									if ((Boolean) properties.get(fldPropName)
											.getValue()) {
										if (!first) {
											fldsString += ",";
										} else {
											first = false;
										}
										fldsString += fld;
										String fldToken = fldPropName
												+ "_token";
										String token = properties.get(fldToken)
												.getValueAsString();
										fieldMap.put(fld, token);
									}
								}
								query.put("restpath", restpath);
								query.put("path", curPath);
								query.put("whereclause", wc);
								query.put("fields", fldsString );
								query.put("outfields", fields);
								query.put("tokenMap", fieldMap);
								query.put("headerconfig", lyrHeaderCfg);
								query.put("usingdist", usingDist);
								query.put("distunits", distUnits);
								query.put("disttoken", distToken);
								query.put("itemconfig", itemConfig);
								query.put("layer", curLyr);
								UUID uid = UUID.randomUUID();
								query.put("id", uid);
								queries.add(query);
								//layerMap.put(layers.get(k).getName(), fieldMap);
							}
							
						}
						
					}
					
					
				}
				//folderMap.put(folder, serviceMap);
			}
			//connmap.put(connName,folderMap);
		}
		
	}
	
	
	
	private void ExecuteRestQueries(String jsonGeometry, String geoType)
			throws GeometryException, UnsupportedEncodingException {
		String contentType = "application/json";
		HttpClient httpclient = new DefaultHttpClient();
		for (int i = 0; i < queries.size(); ++i) {
			@SuppressWarnings("unchecked")
			HashMap<String, Object> query = (HashMap<String, Object>) queries
					.get(i);
			String path = (String) query.get("restpath");
			String wc = URLEncoder.encode((String) query.get("whereclause"),
					"UTF-8");
			String geo = URLEncoder.encode(jsonGeometry, "UTF-8");
			String fields = (String) query.get("fields");
			@SuppressWarnings("unchecked")
			HashMap<String, String> tokenMap = (HashMap<String, String>) query
					.get("tokenMap");
			String itemConfig = (String) query.get("itemconfig");
			//
			String args = "where="
					+ wc
					+ "&objectIds=&time=&geometry="
					+ geo
					+ "&geometryType="
					+ geoType
					+ "&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields="
					+ fields
					+ "&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=&gdbVersion=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&f=json";
			String uri = path + args;
			try {
				HttpPost httppost = new HttpPost(uri);
				httppost.setHeader("Accept", contentType);
				HttpResponse response = httpclient.execute(httppost);

				HttpEntity entity = response.getEntity();
				if (entity != null) {
					InputStream instream = entity.getContent();
					try {
						// instream.read();
						BufferedReader br = new BufferedReader(
								new InputStreamReader((instream)));
						String output = "";
						String ln;
						while ((ln = br.readLine()) != null) {
							output += ln;
						}
						JsonFactory jf = new JsonFactory();
						JsonParser jp = jf.createJsonParser(output);
						FeatureSet fset = FeatureSet.fromJson(jp);
						HashMap<String, Object> tuple = new HashMap<String, Object>();
						String lyr = (String)query.get("layer");
						String lyrheadercfg = (String)query.get("headerconfig");
						Boolean calcdist = (Boolean)query.get("usingdist");
						String distToken = (String)query.get("disttoken");
						String distUnits = (String)query.get("distunits");
						String id = query.get("id").toString();
						tuple.put("fset",  fset);
						tuple.put("tokenmap", tokenMap);
						tuple.put("config", itemConfig);
						tuple.put("layer", lyr);
						tuple.put("lyrheader", lyrheadercfg);
						tuple.put("calcdist", calcdist);
						tuple.put("distunits", distUnits);
						tuple.put("disttoken", distToken);
						responseMap.put(id, tuple);
						

					} catch (IOException ex) {
						// In case of an IOException the connection will be
						// released
						// back to the connection manager automatically
						LOG.error(ex);
						throw ex;
					} catch (RuntimeException ex) {
						// In case of an unexpected exception you may want to
						// abort
						// the HTTP request in order to shut down the underlying
						// connection immediately.
						LOG.error(ex);
						httppost.abort();
						throw ex;
					} finally {
						// Closing the input stream will trigger connection
						// release
						try {
							instream.close();
						} catch (Exception ignore) {
						}
					}
				}

			} catch (Exception ex) {
				LOG.error(ex);
				ex.printStackTrace();
			}

		}
	}
	
	private String GetDistAsString(Graphic g, SpatialReference inputSr, String units)
	{
		com.esri.core.geometry.Geometry geo = g.getGeometry();
		com.esri.core.geometry.Geometry curGeo;
		
		if(!inputSr.equals(srBuffer))
		{
			curGeo = GeometryEngine.project(geo, inputSr, srBuffer);
		}
		else
		{
			curGeo=geo;
		}
		double tmpDist = GeometryEngine.distance(inGeometry, curGeo, srBuffer);
		UnitConverter uc = new UnitConverter();
		int inUnitWkid = uc.findWkid(srBuffer.getUnit().getName());
		String cn = uc.findConnonicalName(units);
		int outUnitWkid = uc.findWkid(cn);
		double dist;
		if(inUnitWkid!=outUnitWkid)
		{
			dist = uc.Convert(tmpDist, inUnitWkid, outUnitWkid);
		}
		else
		{
			dist=tmpDist;
		}
		
		DecimalFormat df = new DecimalFormat("#.00");
		return df.format(dist);
	}
	
	private void ParseResponses(String timestamp, String file)
	{
		Set<String> keys = responseMap.keySet();
		Iterator<String> it = keys.iterator();
		String body = "";
		while(it.hasNext())
		{
			String k = it.next();
			@SuppressWarnings("unchecked")
			HashMap<String, Object> response = (HashMap<String, Object>) responseMap.get(k);
			FeatureSet fset = (FeatureSet)response.get("fset");
			String cfg = (String)response.get("config");
			@SuppressWarnings("unchecked")
			HashMap<String,Object>tokenmap=(HashMap<String, Object>)response.get("tokenmap");
			String layer = (String)response.get("layer");
			Graphic[] features = fset.getGraphics();
			String lyrHeader = (String)response.get("lyrheader");
			if(!lyrHeader.isEmpty())
			{
				lyrHeader = "<h3>"+lyrHeader+"</h3>";
			}
			String items = "";
			
			
			items += "<b>"+layer.toUpperCase() + ": </b>";
			
			Boolean usingDist = (Boolean)response.get("calcdist");
			String distUnits = (String)response.get("distunits");
			String distToken = (String)response.get("disttoken");
			SpatialReference fsetSr = fset.getSpatialReference();
			for (int i=0; i<features.length;++i)
			{
				Graphic f = features[i];
				Map<String, Object> att = f.getAttributes();
				Set<String> fields = tokenmap.keySet();
				Iterator<String> itFields = fields.iterator();
				String item = cfg;
				if(usingDist)
				{
					String d = this.GetDistAsString(f, fsetSr, distUnits);
					item = item.replace(distToken, d);
				}
				while(itFields.hasNext())
				{
					String fldname = itFields.next();
					String token = (String) tokenmap.get(fldname);
					item = item.replace(token, att.get(fldname).toString());
					
					if(i>0)
					{
						items += ", ";
					}
					items += item;
					
				}
			}
			items = "<p>"+items+"</p>";
			body += lyrHeader + items;
		}
		String content = "";
		   //File file = new File("C:/Dev/Java/DefenseSolution/defense-geometry-processor/src/main/resources/ReportTemplate.html"); //for ex foo.txt
		   try {
			   //String name = this.getClass().getName();
		       InputStream is = this.getClass().getClassLoader().getResourceAsStream("ReportTemplate.html");
		       //FileInputStream is = new FileInputStream(file);
			   BufferedReader br = new BufferedReader(new InputStreamReader(is));
		       String ln;
		       while ((ln = br.readLine()) != null) {
					content += ln;
				}
		       String title = properties.get("title").getValueAsString();
		       String header = properties.get("header").getValueAsString();
		       if(!timestamp.isEmpty())
		       {
		    	   String tsToken = properties.get("timestamptoken").getValueAsString();
		    	   title = title.replace(tsToken, timestamp);
		    	   header = header.replace(tsToken, timestamp);
		    	   body = body.replace(tsToken,  timestamp);
		       }
		       content = content.replace("[$TITLE]", "<h1>" +title+"</h1>");
		       content = content.replace("[$HEADING]", "<h2>" +header+"</h2>");
		       content = content.replace("[$BODY]", body);
		       br.close();
		       File dir = new File("assets/reports");
		       if(!dir.exists())
		       {
		    	   dir.mkdir();
		       }
		       String filename = "assets/reports/" + file;
		      
		       File outfile = new File(filename);
		       
		       FileOutputStream fos = new FileOutputStream(outfile);
		       OutputStreamWriter osw = new OutputStreamWriter(fos);    
		       Writer w = new BufferedWriter(osw);
		       w.write(content);
		       w.close();
		   } catch (IOException e) {
		       e.printStackTrace();
		   }
		   
	}

}