package org.zkoss.zssex.util;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.imageio.ImageIO;

import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.zkoss.chart.Chart;
import org.zkoss.json.JSONObject;
import org.zkoss.lang.Library;
import org.zkoss.util.logging.Log;
import org.zkoss.zkex.util.Base64Coder;
import org.zkoss.zss.model.SChart;
import org.zkoss.zssex.ui.ZssCharts;

public class ChartDrawer {
	private static final Log logger = Log.lookup(ChartDrawer.class.getName());
	
	/**
	 * Output PNG image picture from SChart
	 * @param chartInfo inner chart data
	 * @param transparency java.awt.Transparency
	 * @return image file
	 * @throws IOException 
	 */
	static int count = 1;
	private static String RENDER_SERVER_URL = Library.getProperty("org.zkoss.zss.chart.render.server.url");
	private static String RENDER_SERVER_SCALE = Library.getProperty("org.zkoss.zss.chart.render.server.scale");
	// millisecond
	private static String CONNECTION_TIMEOUT = Library.getProperty("org.zkoss.zss.chart.render.server.timeout");
	
	public static BufferedImage drawChartImage(SChart chartInfo, int transparency) throws IOException {
		BufferedImage bufferedImage = null;
		
		if(RENDER_SERVER_URL == null) {
			JFreeChart jfchart = JFreeChartHelper.drawJFreeChart(chartInfo);
			bufferedImage = jfchart.createBufferedImage(
				chartInfo.getAnchor().getWidth(), chartInfo.getAnchor().getHeight(), transparency, new ChartRenderingInfo());
		} else {
			ZssCharts zssCharts = HighchartsHelper.createCharts(chartInfo);
			HighchartsHelper.drawCharts(zssCharts, chartInfo);
			Chart c = zssCharts.getPlotData().getChart();
			c.setWidth(chartInfo.getAnchor().getWidth());
			c.setHeight(chartInfo.getAnchor().getHeight());
			
			JSONObject obj = new JSONObject();
			String chartJSON = zssCharts.getPlotData().toJSONString();
			// syntax ';;;;; and ;;;' are used in escaping in ChartDrawer class for export
			// SEE setupAxis() in HighchartsHelper class 
			chartJSON = chartJSON.replace("';;;;;", "function(){");
			chartJSON = chartJSON.replace(";;;'", ";}");
			chartJSON = chartJSON.replace("\\'", "'");

			obj.put("infile", chartJSON);
			if(RENDER_SERVER_SCALE != null) obj.put("scale", RENDER_SERVER_SCALE);
			
			HttpURLConnection connection = null;
			int timeout = CONNECTION_TIMEOUT != null ? Integer.parseInt(CONNECTION_TIMEOUT) : 10000;
			
			try{
				connection = (HttpURLConnection) new URL(RENDER_SERVER_URL).openConnection();
				logger.debug("Fetch chart picture via connection: %s", RENDER_SERVER_URL);
				
				connection.setRequestMethod("POST");
				connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
				connection.setRequestProperty("Accept","*/*");
				connection.setDoInput(true);
				connection.setDoOutput(true);
				connection.setConnectTimeout(timeout);
				connection.setReadTimeout(timeout);
				connection.connect();
								
				DataOutputStream out = new DataOutputStream (connection.getOutputStream ());
				out.write(obj.toJSONString().getBytes("UTF-8"));
				out.flush();
				out.close();
								
				BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
				String output;
				StringBuffer sb = new StringBuffer();
				while ((output = in.readLine()) != null)
					sb.append(output);
				in.close();
				
				ByteArrayInputStream bis = new ByteArrayInputStream(Base64Coder.decode(sb.toString()));
		        bufferedImage = ImageIO.read(bis);
			} catch (IOException e) {
				throw new IOException("Make sure the rendering server and network work well. Server URL: " + RENDER_SERVER_URL, e);
			} finally {
				if(connection != null)
					connection.disconnect();
			}
		}
		
		return bufferedImage;
	}
}
