// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.consoleproxy;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import com.cloud.consoleproxy.util.Logger;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class ConsoleProxyThumbnailHandler implements HttpHandler {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyThumbnailHandler.class);
	
	public ConsoleProxyThumbnailHandler() {
	}

	public void handle(HttpExchange t) throws IOException {
		try {
	        Thread.currentThread().setName("JPG Thread " + 
	        		Thread.currentThread().getId() + " " + t.getRemoteAddress());
	        
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug("ScreenHandler " + t.getRequestURI());
	        
	        long startTick = System.currentTimeMillis();
			doHandle(t);
			
	        if(s_logger.isDebugEnabled())
	        	s_logger.debug(t.getRequestURI() + "Process time " + (System.currentTimeMillis() - startTick) + " ms");
		} catch (IllegalArgumentException e) {
			String response = "Bad query string";
			s_logger.error(response + ", request URI : " + t.getRequestURI());
			t.sendResponseHeaders(200, response.length());
			OutputStream os = t.getResponseBody();
			os.write(response.getBytes());
			os.close();
		} catch(OutOfMemoryError e) {
			s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
			System.exit(1);
		} catch (Throwable e) {
			s_logger.error("Unexpected exception while handing thumbnail request, ", e);
			
			String queries = t.getRequestURI().getQuery();
			Map<String, String> queryMap = getQueryMap(queries);
			int width = 0;
			int height = 0;
			String ws = queryMap.get("w");
			String hs = queryMap.get("h");
			try {
				width = Integer.parseInt(ws);
				height = Integer.parseInt(hs);
			} catch (NumberFormatException ex) {
			}
			width = Math.min(width, 800);
			height = Math.min(height, 600);
			
			BufferedImage img = generateTextImage(width, height, "Cannot Connect");
			ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
			javax.imageio.ImageIO.write(img, "jpg", bos);
			byte[] bs = bos.toByteArray();
			Headers hds = t.getResponseHeaders();
			hds.set("Content-Type", "image/jpeg");
			hds.set("Cache-Control", "no-cache");
			hds.set("Cache-Control", "no-store");
			t.sendResponseHeaders(200, bs.length);
			OutputStream os = t.getResponseBody();
			os.write(bs);
			os.close();
			s_logger.error("Cannot get console, sent error JPG response for " + t.getRequestURI());
			return;
		} finally {
			t.close();
		}
	}
	
	private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
		String queries = t.getRequestURI().getQuery();
		Map<String, String> queryMap = getQueryMap(queries);
		int width = 0;
		int height = 0;
		int port = 0;
		String ws = queryMap.get("w");
		String hs = queryMap.get("h");
		String host = queryMap.get("host");
		String portStr = queryMap.get("port");
		String sid = queryMap.get("sid");
		String tag = queryMap.get("tag");
		String ticket = queryMap.get("ticket");
		String console_url = queryMap.get("consoleurl");
		String console_host_session = queryMap.get("sessionref");

		if(tag == null)
			tag = "";
		
		if (ws == null || hs == null || host == null || portStr == null || sid == null ) {
			throw new IllegalArgumentException();
		}
		try {
			width = Integer.parseInt(ws);
			height = Integer.parseInt(hs);
			port = Integer.parseInt(portStr);
		} catch (NumberFormatException e) {
			throw new IllegalArgumentException(e);
		}

		ConsoleProxyClientParam param = new ConsoleProxyClientParam();
		param.setClientHostAddress(host);
		param.setClientHostPort(port);
		param.setClientHostPassword(sid);
		param.setClientTag(tag);
		param.setTicket(ticket);
		param.setClientTunnelUrl(console_url);
		param.setClientTunnelSession(console_host_session);
		
		ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(param);
		
		if (!viewer.isHostConnected()) {
			// use generated image instead of static
			BufferedImage img = generateTextImage(width, height, "Connecting");
			ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
			javax.imageio.ImageIO.write(img, "jpg", bos);
			byte[] bs = bos.toByteArray();
			Headers hds = t.getResponseHeaders();
			hds.set("Content-Type", "image/jpeg");
			hds.set("Cache-Control", "no-cache");
			hds.set("Cache-Control", "no-store");
			t.sendResponseHeaders(200, bs.length);
			OutputStream os = t.getResponseBody();
			os.write(bs);
			os.close();
			
			if(s_logger.isInfoEnabled())
				s_logger.info("Console not ready, sent dummy JPG response");
			return;
		}
		
		{
			Image scaledImage = viewer.getClientScaledImage(width, height);
			BufferedImage bufferedImage = new BufferedImage(width, height,
					BufferedImage.TYPE_3BYTE_BGR);
			Graphics2D bufImageGraphics = bufferedImage.createGraphics();
			bufImageGraphics.drawImage(scaledImage, 0, 0, null);
			ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
			javax.imageio.ImageIO.write(bufferedImage, "jpg", bos);
			byte[] bs = bos.toByteArray();
			Headers hds = t.getResponseHeaders();
			hds.set("Content-Type", "image/jpeg");
			hds.set("Cache-Control", "no-cache");
			hds.set("Cache-Control", "no-store");
			t.sendResponseHeaders(200, bs.length);
			OutputStream os = t.getResponseBody();
			os.write(bs);
			os.close();
		}
	}
	
	public static BufferedImage generateTextImage(int w, int h, String text) {
		BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D g = img.createGraphics();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, w, h);
		g.setColor(Color.WHITE);
		try {
			g.setFont(new Font(null, Font.PLAIN, 12));
	  		FontMetrics fm = g.getFontMetrics();
	  		int textWidth = fm.stringWidth(text);
	  		int startx = (w-textWidth) / 2;
	  		if(startx < 0)
	  			startx = 0;
	  		g.drawString(text, startx, h/2);
		} catch (Throwable e) {
			s_logger.warn("Problem in generating text to thumnail image, return blank image");
		}
		return img;
	}

	public static Map<String, String> getQueryMap(String query) {
		String[] params = query.split("&");
		Map<String, String> map = new HashMap<String, String>();
		for (String param : params) {
			String name = param.split("=")[0];
			String value = param.split("=")[1];
			map.put(name, value);
		}
		return map;
	}
}
