// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
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;
	}
}
