/*******************************************************************************
 * Copyright (c) 2009 IBM Corporation and others All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.rhino.debugger;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.wst.jsdt.debug.internal.rhino.transport.JSONConstants;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.RhinoRequest;
import org.eclipse.wst.jsdt.debug.internal.rhino.transport.RhinoResponse;

/**
 * Rhino request handler used to craft response bodies for given JSON requests
 * 
 * @since 1.0
 */
public class RequestHandler {

	public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$
	private RhinoDebuggerImpl debugger;

	/**
	 * Constructor
	 * 
	 * @param debugger
	 */
	public RequestHandler(RhinoDebuggerImpl debugger) {
		this.debugger = debugger;
	}

	/**
	 * Handles a general request - delegating to the correct command type
	 * 
	 * @param request
	 * @return
	 */
	public RhinoResponse handleRequest(RhinoRequest request) {
		String command = request.getCommand();
		RhinoResponse response = new RhinoResponse(request.getSequence(), command);
		try {
			if (command.equals(JSONConstants.VERSION)) {
				handleVersionRequest(request, response);
			} else if (command.equals(JSONConstants.SUSPEND)) {
				handleSuspendRequest(request, response);
			} else if (command.equals(JSONConstants.CONTINUE)) {
				handleContinueRequest(request, response);
			} else if (command.equals(JSONConstants.DISPOSE)) {
				handleDisposeRequest(request, response);
			} else if (command.equals(JSONConstants.THREADS)) {
				handleThreadsRequest(request, response);
			} else if (command.equals(JSONConstants.THREAD)) {
				handleThreadRequest(request, response);
			} else if (command.equals(JSONConstants.FRAMES)) {
				handleFramesRequest(request, response);
			} else if (command.equals(JSONConstants.FRAME)) {
				handleFrameRequest(request, response);
			} else if (command.equals(JSONConstants.SCRIPTS)) {
				handleScriptsRequest(request, response);
			} else if (command.equals(JSONConstants.SCRIPT)) {
				handleScriptRequest(request, response);
			} else if (command.equals(JSONConstants.EVALUATE)) {
				handleEvaluateRequest(request, response);
			} else if (command.equals(JSONConstants.LOOKUP)) {
				handleLookupRequest(request, response);
			} else if (command.equals(JSONConstants.BREAKPOINTS)) {
				handleBreakpointsRequest(request, response);
			} else if (command.equals(JSONConstants.BREAKPOINT)) {
				handleBreakpointRequest(request, response);
			} else if (command.equals(JSONConstants.SETBREAKPOINT)) {
				handleSetBreakpointRequest(request, response);
			} else if (command.equals(JSONConstants.CLEARBREAKPOINT)) {
				handleClearBreakpointRequest(request, response);
			} else {
				response.setSuccess(false);
				response.setMessage("command not supported"); //$NON-NLS-1$
			}
		} catch (Throwable t) {
			response.setSuccess(false);
			response.setMessage(t.getClass().getName() + " - " + t.getMessage()); //$NON-NLS-1$
			t.printStackTrace();
		}
		return response;
	}

	/**
	 * Handles a clear breakpoint request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleClearBreakpointRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long breakpointId = numberToLong((Number) arguments.get(JSONConstants.BREAKPOINT_ID));
		if (breakpointId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.BREAKPOINT_ID));
			return;
		}
		Breakpoint breakpoint = debugger.clearBreakpoint(breakpointId);
		if (breakpoint == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		response.getBody().put(JSONConstants.BREAKPOINT, breakpoint.toJSON());
	}

	/**
	 * Handles a set breakpoint request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleSetBreakpointRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long scriptId = numberToLong((Number) arguments.get(JSONConstants.SCRIPT_ID));
		Integer line = numberToInteger((Number) arguments.get(JSONConstants.LINE));
		String function = (String) arguments.get(JSONConstants.FUNCTION);
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		String condition = (String) arguments.get(JSONConstants.CONDITION);
		Breakpoint breakpoint = debugger.setBreakpoint(scriptId, line, function, condition, threadId);
		if(breakpoint != null) {
			response.getBody().put(JSONConstants.BREAKPOINT, breakpoint.toJSON());
		}
	}

	/**
	 * Handles a breakpoint request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleBreakpointRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long breakpointId = numberToLong((Number) arguments.get(JSONConstants.BREAKPOINT_ID));
		if (breakpointId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.BREAKPOINT_ID));
			return;
		}
		Breakpoint breakpoint = debugger.getBreakpoint(breakpointId);
		if (breakpoint == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		response.getBody().put(JSONConstants.BREAKPOINT, breakpoint.toJSON());
	}

	/**
	 * Handles a breakpoints request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleBreakpointsRequest(RhinoRequest request, RhinoResponse response) {
		Collection breakpoints = debugger.getBreakpoints();
		response.getBody().put(JSONConstants.BREAKPOINTS, breakpoints);
	}

	/**
	 * Handles an evaluate request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleEvaluateRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.THREAD_ID));
			return;
		}
		Long frameId = numberToLong((Number) arguments.get(JSONConstants.FRAME_ID));
		if (frameId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.FRAME_ID));
			return;
		}
		String evaluate = (String) arguments.get(JSONConstants.EXPRESSION);
		if (evaluate == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.EXPRESSION));
			return;
		}
		StackFrame frame = debugger.getFrame(threadId, frameId);
		if (frame == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		Object result = frame.evaluate(evaluate);
		response.getBody().put(JSONConstants.EVALUATE, result);
	}

	/**
	 * Handles a lookup request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleLookupRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.THREAD_ID));
			return;
		}
		Long frameId = numberToLong((Number) arguments.get(JSONConstants.FRAME_ID));
		if (frameId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.FRAME_ID));
			return;
		}
		Long handle = numberToLong((Number) arguments.get(JSONConstants.REF));
		if (handle == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.REF));
			return;
		}
		StackFrame frame = debugger.getFrame(threadId, frameId);
		if (frame == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		Object result = frame.lookup(handle);
		response.getBody().put(JSONConstants.LOOKUP, result);
	}

	/**
	 * Handles a script request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleScriptRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long scriptId = numberToLong((Number) arguments.get(JSONConstants.SCRIPT_ID));
		if (scriptId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.SCRIPT_ID));
			return;
		}
		ScriptSource script = debugger.getScript(scriptId);
		if (script == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		response.getBody().put(JSONConstants.SCRIPT, script.toJSON());
	}

	/**
	 * Handles a scripts request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleScriptsRequest(RhinoRequest request, RhinoResponse response) {
		List scriptIds = debugger.getScriptIds();
		response.getBody().put(JSONConstants.SCRIPTS, scriptIds);
	}

	/**
	 * Handles a frame request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleFrameRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.THREAD_ID));
			return;
		}
		Long frameId = numberToLong((Number) arguments.get(JSONConstants.FRAME_ID));
		if (frameId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.FRAME_ID));
			return;
		}
		StackFrame frame = debugger.getFrame(threadId, frameId);
		if (frame == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		response.getBody().put(JSONConstants.FRAME, frame.toJSON());
	}

	/**
	 * Handles a frames request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleFramesRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.THREAD_ID));
			return;
		}
		List frameIds = debugger.getFrameIds(threadId);
		response.getBody().put(JSONConstants.FRAMES, frameIds);
	}

	/**
	 * Handles a thread request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleThreadRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			response.setSuccess(false);
			response.setMessage(missingArgument(JSONConstants.THREAD_ID));
			return;
		}
		ThreadData threadData = debugger.getThreadData(threadId);
		if (threadData == null) {
			response.setSuccess(false);
			response.setMessage(JSONConstants.NOT_FOUND);
			return;
		}
		response.getBody().put(JSONConstants.THREAD, threadData.toJSON());
	}

	/**
	 * Reports a missing argument
	 * 
	 * @param key
	 * @return
	 */
	private String missingArgument(String key) {
		// TODO NLS this
		return "Missing Argument: "+key; //$NON-NLS-1$
	}

	/**
	 * Handles a threads request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleThreadsRequest(RhinoRequest request, RhinoResponse response) {
		List threadIds = debugger.getThreadIds();
		response.getBody().put(JSONConstants.THREADS, threadIds);
	}

	/**
	 * Handles a dispose request by disconnecting the underlying {@link RhinoDebuggerImpl}
	 * 
	 * @param request
	 * @param response
	 */
	private void handleDisposeRequest(RhinoRequest request, RhinoResponse response) {
		debugger.disconnect();
	}

	/**
	 * Handles a continue request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleContinueRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			debugger.resumeAll();
			return;
		}
		String stepType = (String) arguments.get(JSONConstants.STEP);
		debugger.resume(threadId, stepType);
	}

	/**
	 * Handles a suspend request
	 * 
	 * @param request
	 * @param response
	 */
	private void handleSuspendRequest(RhinoRequest request, RhinoResponse response) {
		Map arguments = request.getArguments();
		Long threadId = numberToLong((Number) arguments.get(JSONConstants.THREAD_ID));
		if (threadId == null) {
			debugger.suspendAll();
			return;
		}
		debugger.suspend(threadId);
	}

	/**
	 * Wrappers the given {@link Number} as a {@link Long}
	 * 
	 * @param number
	 * @return a new {@link Long}
	 */
	private static Long numberToLong(Number number) {
		if (number == null)
			return null;
		return new Long(number.longValue());
	}

	/**
	 * Wrappers the given {@link Number} as an {@link Integer}
	 * 
	 * @param number
	 * @return a new {@link Integer}
	 */
	private Integer numberToInteger(Number number) {
		if (number == null) {
			return null;
		}
		return new Integer(number.intValue());
	}

	/**
	 * Appends version infos to the given response body
	 * 
	 * @param request
	 * @param response
	 * 
	 * @see JSONConstants#ECMASCRIPT_VERSION
	 * @see JSONConstants#JAVASCRIPT_VERSION
	 * @see JSONConstants#VM_NAME
	 * @see JSONConstants#VM_VENDOR
	 * @see JSONConstants#VM_VERSION
	 */
	private void handleVersionRequest(RhinoRequest request, RhinoResponse response) {
		Map body = response.getBody();
		body.put(JSONConstants.JAVASCRIPT_VERSION, VERSION_1_6);
		body.put(JSONConstants.ECMASCRIPT_VERSION, "3"); //$NON-NLS-1$
		body.put(JSONConstants.VM_NAME, "Rhino"); //$NON-NLS-1$
		body.put(JSONConstants.VM_VERSION, VERSION_1_6);
		body.put(JSONConstants.VM_VENDOR, "Mozilla"); //$NON-NLS-1$
	}
}
