// 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.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();
		}
	}
}
