// 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.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
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 ConsoleProxyAjaxHandler implements HttpHandler {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyAjaxHandler.class);
	
	public ConsoleProxyAjaxHandler() {
	}
	
	public void handle(HttpExchange t) throws IOException {
		try {
	        if(s_logger.isTraceEnabled())
	        	s_logger.trace("AjaxHandler " + t.getRequestURI());
	        
	        long startTick = System.currentTimeMillis();
	        
	        doHandle(t);
	        
	        if(s_logger.isTraceEnabled())
	        	s_logger.trace(t.getRequestURI() + " process time " + (System.currentTimeMillis() - startTick) + " ms");
		} catch (IOException e) {
			throw e;
		} catch (IllegalArgumentException e) {
			s_logger.warn("Exception, ", e);
			t.sendResponseHeaders(400, -1);		// bad request
		} catch(Throwable e) {
			s_logger.error("Unexpected exception, ", e);
			t.sendResponseHeaders(500, -1);		// server error
		} finally {
			t.close();
		}
	}
	
	private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
		String queries = t.getRequestURI().getQuery();
		if(s_logger.isTraceEnabled())
			s_logger.trace("Handle AJAX request: " + queries);
		
		Map<String, String> queryMap = ConsoleProxyHttpHandlerHelper.getQueryMap(queries);
		
		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 ajaxSessionIdStr = queryMap.get("sess");
		String eventStr = queryMap.get("event");
		String console_url = queryMap.get("consoleurl");
		String console_host_session = queryMap.get("sessionref");
		
		if(tag == null)
			tag = "";
		
		long ajaxSessionId = 0;
		int event = 0;
		
		int port;

		if(host == null || portStr == null || sid == null) 
			throw new IllegalArgumentException();
		
		try {
			port = Integer.parseInt(portStr);
		} catch (NumberFormatException e) {
			s_logger.warn("Invalid number parameter in query string: " + portStr);
			throw new IllegalArgumentException(e);
		}

		if(ajaxSessionIdStr != null) {
			try {
				ajaxSessionId = Long.parseLong(ajaxSessionIdStr);
			} catch (NumberFormatException e) {
				s_logger.warn("Invalid number parameter in query string: " + ajaxSessionIdStr);
				throw new IllegalArgumentException(e);
			}
		}

		if(eventStr != null) {
			try {
				event = Integer.parseInt(eventStr);
			} catch (NumberFormatException e) {
				s_logger.warn("Invalid number parameter in query string: " + eventStr);
				throw new IllegalArgumentException(e);
			}
		}
		
		ConsoleProxyClient viewer = null;
		try {
			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);
			
			viewer = ConsoleProxy.getAjaxVncViewer(param, ajaxSessionIdStr);
		} catch(Exception e) {

			s_logger.warn("Failed to create viewer due to " + e.getMessage(), e);

			String[] content = new String[] {
				"<html><head></head><body>",
				"<div id=\"main_panel\" tabindex=\"1\">",
				"<p>Access is denied for the console session. Please close the window and retry again</p>",
				"</div></body></html>"
			};
			
			StringBuffer sb = new StringBuffer();
			for(int i = 0; i < content.length; i++)
				sb.append(content[i]);
			
			sendResponse(t, "text/html", sb.toString());
			return;
		}
		
		if(event != 0) {
			if(ajaxSessionId != 0 && ajaxSessionId == viewer.getAjaxSessionId()) {
				if(event == 7) {
					// client send over an event bag
					InputStream is = t.getRequestBody();
					handleClientEventBag(viewer, convertStreamToString(is, true));
				} else {
					handleClientEvent(viewer, event, queryMap);
				}
				sendResponse(t, "text/html", "OK");
			} else {
				if(s_logger.isDebugEnabled())
					s_logger.debug("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
				
				sendResponse(t, "text/html", "Invalid ajax client session id");
			}
		} else {
			if(ajaxSessionId != 0 && ajaxSessionId != viewer.getAjaxSessionId()) {
				s_logger.info("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
				handleClientKickoff(t, viewer);
			} else if(ajaxSessionId == 0) {
				if(s_logger.isDebugEnabled())
					s_logger.debug("Ajax request indicates a fresh client start");
		
				String title = queryMap.get("t");
				String guest = queryMap.get("guest");
				handleClientStart(t, viewer, title != null ? title : "", guest);
			} else {
				
				if(s_logger.isTraceEnabled())
					s_logger.trace("Ajax request indicates client update");
				
				handleClientUpdate(t, viewer);
			}
		}
	}
	
	private static String convertStreamToString(InputStream is, boolean closeStreamAfterRead) { 
		BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
		StringBuilder sb = new StringBuilder(); 
		String line = null; 
		try { 
			while ((line = reader.readLine()) != null) { 
				sb.append(line + "\n"); 
			} 
		} catch (IOException e) {
			s_logger.warn("Exception while reading request body: ", e);
		} finally {
			if(closeStreamAfterRead) {
				try { 
					is.close(); 
				} catch (IOException e) { 
				} 
			}
		} 
		return sb.toString(); 
	} 	
	
	private void sendResponse(HttpExchange t, String contentType, String response) throws IOException {
		Headers hds = t.getResponseHeaders();
		hds.set("Content-Type", contentType);
	
		t.sendResponseHeaders(200, response.length());
		OutputStream os = t.getResponseBody();
		try {
			os.write(response.getBytes());
		} finally {
			os.close();
		}
	}
	
	@SuppressWarnings("deprecation")
	private void handleClientEventBag(ConsoleProxyClient viewer, String requestData) {
		if(s_logger.isTraceEnabled())
			s_logger.trace("Handle event bag, event bag: " + requestData);
		
		int start = requestData.indexOf("=");
		if(start < 0)
			start = 0;
		else if(start > 0)
			start++;
		String data = URLDecoder.decode(requestData.substring(start));
		String[] tokens = data.split("\\|");
		if(tokens != null && tokens.length > 0) {
			int count = 0;
			try {
				count = Integer.parseInt(tokens[0]);
				int parsePos = 1;
				int type, event, x, y, code, modifiers;
				for(int i = 0; i < count; i++) {
					type = Integer.parseInt(tokens[parsePos++]);
					if(type == 1) 	{
						// mouse event
						event = Integer.parseInt(tokens[parsePos++]);
						x = Integer.parseInt(tokens[parsePos++]);
						y = Integer.parseInt(tokens[parsePos++]);
						code = Integer.parseInt(tokens[parsePos++]);
						modifiers = Integer.parseInt(tokens[parsePos++]);
						
						Map<String, String> queryMap = new HashMap<String, String>();
						queryMap.put("event", String.valueOf(event));
						queryMap.put("x", String.valueOf(x));
						queryMap.put("y", String.valueOf(y));
						queryMap.put("code", String.valueOf(code));
						queryMap.put("modifier", String.valueOf(modifiers));
						handleClientEvent(viewer, event, queryMap);
					} else {
						// keyboard event
						event = Integer.parseInt(tokens[parsePos++]);
						code = Integer.parseInt(tokens[parsePos++]);
						modifiers = Integer.parseInt(tokens[parsePos++]);
						
						Map<String, String> queryMap = new HashMap<String, String>();
						queryMap.put("event", String.valueOf(event));
						queryMap.put("code", String.valueOf(code));
						queryMap.put("modifier", String.valueOf(modifiers));
						handleClientEvent(viewer, event, queryMap);
					}
				}
			} catch(NumberFormatException e) {
				s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
			} catch(Exception e) {
				s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
			} catch(OutOfMemoryError e) {
				s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
				System.exit(1);
			}
		}
	}
	
	private void handleClientEvent(ConsoleProxyClient viewer, int event, Map<String, String> queryMap) {
		int code = 0;
		int x = 0, y = 0;
		int modifiers = 0;
		
		String str;
		switch(event) {
		case 1:		// mouse move
		case 2:		// mouse down
		case 3:		// mouse up
		case 8:		// mouse double click
			str = queryMap.get("x");
			if(str != null) {
				try {
					x = Integer.parseInt(str);
				} catch (NumberFormatException e) {
					s_logger.warn("Invalid number parameter in query string: " + str);
					throw new IllegalArgumentException(e);
				}
			}
			str = queryMap.get("y");
			if(str != null) {
				try {
					y = Integer.parseInt(str);
				} catch (NumberFormatException e) {
					s_logger.warn("Invalid number parameter in query string: " + str);
					throw new IllegalArgumentException(e);
				}
			}
			
			if(event != 1) {
				str = queryMap.get("code");
				try {
					code = Integer.parseInt(str);
				} catch (NumberFormatException e) {
					s_logger.warn("Invalid number parameter in query string: " + str);
					throw new IllegalArgumentException(e);
				}
				
				str = queryMap.get("modifier");
				try {
					modifiers = Integer.parseInt(str);
				} catch (NumberFormatException e) {
					s_logger.warn("Invalid number parameter in query string: " + str);
					throw new IllegalArgumentException(e);
				}
				
				if(s_logger.isTraceEnabled())
					s_logger.trace("Handle client mouse event. event: " + event + ", x: " + x + ", y: " + y + ", button: " + code + ", modifier: " + modifiers);
			} else {
				if(s_logger.isTraceEnabled())
					s_logger.trace("Handle client mouse move event. x: " + x + ", y: " + y);
			}
			viewer.sendClientMouseEvent(InputEventType.fromEventCode(event), x, y, code, modifiers);
			break;
			
		case 4:		// key press
		case 5:		// key down
		case 6:		// key up
			str = queryMap.get("code");
			try {
				code = Integer.parseInt(str);
			} catch (NumberFormatException e) {
				s_logger.warn("Invalid number parameter in query string: " + str);
				throw new IllegalArgumentException(e);
			}
			
			str = queryMap.get("modifier");
			try {
				modifiers = Integer.parseInt(str);
			} catch (NumberFormatException e) {
				s_logger.warn("Invalid number parameter in query string: " + str);
				throw new IllegalArgumentException(e);
			}
			
			if(s_logger.isDebugEnabled())
				s_logger.debug("Handle client keyboard event. event: " + event + ", code: " + code + ", modifier: " + modifiers);
			viewer.sendClientRawKeyboardEvent(InputEventType.fromEventCode(event), code, modifiers);
			break;
			
		default :
			break;
		}
	}
	
	private void handleClientKickoff(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
		String response = viewer.onAjaxClientKickoff();
		t.sendResponseHeaders(200, response.length());
		OutputStream os = t.getResponseBody();
		try {
			os.write(response.getBytes());
		} finally {
			os.close();
		}
	}
	
	private void handleClientStart(HttpExchange t, ConsoleProxyClient viewer, String title, String guest) throws IOException {
		List<String> languages = t.getRequestHeaders().get("Accept-Language");
		String response = viewer.onAjaxClientStart(title, languages, guest);
		
		Headers hds = t.getResponseHeaders();
		hds.set("Content-Type", "text/html");
		hds.set("Cache-Control", "no-cache");
		hds.set("Cache-Control", "no-store");
		t.sendResponseHeaders(200, response.length());
		
		OutputStream os = t.getResponseBody();
		try {
			os.write(response.getBytes());
		} finally {
			os.close();
		}
	}
	
	private void handleClientUpdate(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
		String response = viewer.onAjaxClientUpdate();
		
		Headers hds = t.getResponseHeaders();
		hds.set("Content-Type", "text/javascript");
		t.sendResponseHeaders(200, response.length());
		
		OutputStream os = t.getResponseBody();
		try {
			os.write(response.getBytes());
		} finally {
			os.close();
		}
	}
}
