/*******************************************************************************
 * Copyright (c) 2010 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.crossfire.jsdi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.wst.jsdt.debug.core.jsdi.Location;
import org.eclipse.wst.jsdt.debug.core.jsdi.NullValue;
import org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame;
import org.eclipse.wst.jsdt.debug.core.jsdi.Value;
import org.eclipse.wst.jsdt.debug.core.jsdi.Variable;
import org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine;
import org.eclipse.wst.jsdt.debug.internal.crossfire.Tracing;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.Attributes;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFRequestPacket;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFResponsePacket;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.Commands;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.JSON;

/**
 * Default implementation of {@link StackFrame} for Crossfire
 * 
 * @since 1.0
 */
public class CFStackFrame extends CFMirror implements StackFrame {

	/**
	 * Describes a scope
	 */
	class Scope {
		Number idx = null;
		Number fidx = null;
		Number ref = null;
		public Scope(Number idx, Number fidx, Number ref) {
			this.idx = idx;
			this.fidx = fidx;
			this.ref = ref;
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		public int hashCode() {
			return idx.hashCode() + fidx.hashCode() + ref.hashCode();
		}
		
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if(obj instanceof Scope) {
				Scope s = (Scope) obj;
				return idx.equals(s.idx) && fidx.equals(s.fidx) && ref.equals(s.ref);
			}
			return false;
		}
	}
	
	HashSet scopes = new HashSet();
	
	private int index = -1;
	private String scriptid = null;
	private String funcname = null;
	private int linenumber = -1;
	private List vars = null;
	private Variable thisvar = null;
	private CFLocation loc = null;
	private CFThreadReference thread = null;
	
	/**
	 * Constructor
	 * @param vm
	 * @param json
	 */
	public CFStackFrame(VirtualMachine vm, CFThreadReference thread, Map json) {
		super(vm);
		this.thread = thread;
		Number value = (Number) json.get(Attributes.INDEX);
		if(value != null) {
			index = value.intValue();
		}
		value = (Number) json.get(Attributes.LINE);
		if(value != null) {
			linenumber = value.intValue();
		}
		scriptid = (String) json.get(Attributes.SCRIPT);
		funcname = (String) json.get(Attributes.FUNC);
		
		parseScopes((List) json.get(Attributes.SCOPES));
		parseLocals((Map) json.get(Attributes.LOCALS));
		//scope();
		//allScopes();
	}

	/**
	 * Parses the scopes object node, if there is one
	 * 
	 * @param list the list of scopes
	 */
	void parseScopes(List list) {
		if(list != null) {
			for (Iterator i = list.iterator(); i.hasNext();) {
				Map map = (Map) i.next();
				Scope s = new Scope(
						(Number)map.get(Attributes.INDEX), 
						(Number)map.get(Attributes.FRAME_INDEX), 
						(Number) ((Map)map.get(Attributes.OBJECT)).get(Attributes.HANDLE));
				scopes.add(s);
			}
		}
	}
	
	/**
	 * Read the local variable information from the json mapping
	 * 
	 * @param json
	 */
	void parseLocals(Map json) {
		if(json != null) {
			Object val = json.get(Attributes.VALUE);
			if(val instanceof Map) {
				Map locals = (Map) json.get(Attributes.VALUE); 
				if(locals != null) {
					vars = new ArrayList(locals.size());
					parseVariables(locals, vars);
				}
			}
			else {
				vars = new ArrayList();
			}
			Map thismap = (Map) json.get(Attributes.THIS); 
			thisvar = new CFVariable(crossfire(), this, Attributes.THIS, null, (thismap == null ? new HashMap(0) : thismap));
		}
	}
	
	void parseVariables(Map map, List varcollector) {
		Entry entry = null;
		for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
			entry = (Entry) iter.next();
			if(entry.getValue() instanceof Map) {
				Map info  = (Map) entry.getValue();
				varcollector.add(
						new CFVariable(
								crossfire(), 
								this, 
								(String) entry.getKey(), 
								(Number) info.get(Attributes.HANDLE), 
								info));
			}
			else {
				varcollector.add(
						new CFVariable(
								crossfire(), 
								this, 
								(String) entry.getKey(), 
								null, 
								null));
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame#thisObject()
	 */
	public Variable thisObject() {
		return thisvar;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame#variables()
	 */
	public synchronized List variables() {
		if(vars != null) {
			return vars;
		}
		return Collections.EMPTY_LIST; 
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame#location()
	 */
	public synchronized Location location() {
		if(loc == null) {
			CFScriptReference script = crossfire().findScript(scriptid); 
			if(script != null) {
				loc = new CFLocation(crossfire(), script, funcname, linenumber);
			}
		}
		return loc;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.wst.jsdt.debug.core.jsdi.StackFrame#evaluate(java.lang.String)
	 */
	public Value evaluate(String expression) {
		CFRequestPacket request = new CFRequestPacket(Commands.EVALUATE, thread.id());
		request.setArgument(Attributes.FRAME, new Integer(index));
		request.setArgument(Attributes.EXPRESSION, expression);
		CFResponsePacket response = crossfire().sendRequest(request);
		if(response.isSuccess()) {
			return createValue(response.getBody());
		}
		else if(TRACE) {
			Tracing.writeString("STACKFRAME [failed evaluate request]: "+JSON.serialize(request)); //$NON-NLS-1$
		}
		return virtualMachine().mirrorOfNull();
	}
	
	/**
	 * Returns the index of the frame in the stack
	 * 
	 * @return the frame index
	 */
	public int frameindex() {
		return index;
	}
	
	/**
	 * Looks up the value given its handle ref
	 * 
	 * @param ref
	 * @return the {@link Value} or <code>null</code>
	 */
	public Value lookup(Number ref) {
		if(ref != null) {
			CFRequestPacket request = new CFRequestPacket(Commands.LOOKUP, thread.id());
			request.setArgument(Attributes.HANDLE, ref);
			request.setArgument(Attributes.INCLUDE_SOURCE, Boolean.TRUE);
			CFResponsePacket response = crossfire().sendRequest(request);
			if(response.isSuccess()) {
				return createValue(response.getBody());
			}
			else if(TRACE) {
				Tracing.writeString("STACKFRAME [request for value lookup failed]: "+JSON.serialize(request)); //$NON-NLS-1$
			}
		}
		return crossfire().mirrorOfNull();
	}
	
	/**
	 * Creates the correct type if {@link Value} from the given json mapping
	 * @param json
	 * @return the new {@link Value} or <code>null</code> if one could not be created
	 */
	Value createValue(Object val) {
		//resolve the smallest type from the crossfire insanity
		if(val instanceof Map) {
			Map values = (Map) val;
			Object o = values.get(Attributes.RESULT);
			if(o == null) {
				String type = (String) values.get(Attributes.TYPE);
				if(type != null) {
					return createTypeValue(type, values);
				}
			}
			if(o instanceof Map){
				return new CFObjectReference(crossfire(), this, (Map) o);
			}
			if(o instanceof String) {
				return crossfire().mirrorOf(o.toString());
			}
			else if(o instanceof Number) {
				return crossfire().mirrorOf((Number)o);
			}
		}
		else if(val instanceof Map) {
			return new CFObjectReference(crossfire(), this, (Map) val);
		}
		else if(val instanceof String) {
			String str = (String) val;
			if(CFUndefinedValue.UNDEFINED.equals(str)) {
				return crossfire().mirrorOfUndefined();
			}
			return crossfire().mirrorOf((String) val); 
		}
		else if(val instanceof Number) {
			return crossfire().mirrorOf((Number) val);
		}
		return crossfire().mirrorOfNull();
	}
	
	/**
	 * Create a new {@link Value} based on the given type
	 * 
	 * @param type the type
	 * @param map the map of value information
	 * @return the new {@link Value} for the given type or {@link NullValue} if a value cannot be computed
	 */
	Value createTypeValue(String type, Map map) {
		if(CFUndefinedValue.UNDEFINED.equals(type)) {
			return crossfire().mirrorOfUndefined();
		}
		if(CFStringValue.STRING.equals(type)) {
			return crossfire().mirrorOf(map.get(Attributes.VALUE).toString());
		}
		if(CFObjectReference.OBJECT.equals(type) || Attributes.REF.equals(type)) {
			return new CFObjectReference(crossfire(), this, map);
		}
		if(CFArrayReference.ARRAY.equals(type)) {
			return new CFArrayReference(crossfire(), this, map);
		}
		if(CFFunctionReference.FUNCTION.equals(type)) {
			return new CFFunctionReference(crossfire(), this, map);
		}
		return crossfire().mirrorOfNull();
	}
	
	/**
	 * Returns if this stack frame is visible
	 * 
	 * @param variable
	 * @return true if this frame is visible, false otherwise
	 */
	public synchronized boolean isVisible(CFVariable variable) {
		return vars != null && (thisvar == variable || vars.contains(variable));
	}
	
	/**
	 * Gets all of the scopes from Firebug
	 */
	void allScopes() {
		CFRequestPacket request = new CFRequestPacket(Commands.SCOPES, thread.id());
		request.setArgument(Attributes.FRAME_NUMBER, new Integer(index));
		CFResponsePacket response = crossfire().sendRequest(request);
		if(response.isSuccess()) {
			List list = (List) response.getBody().get(Attributes.SCOPES);
			if(list != null) {
				parseScopes(list);
			}
		}
		else if(TRACE) {
			Tracing.writeString("VM [failed scopes request]: "+JSON.serialize(request)); //$NON-NLS-1$
		}
	}
	
	/**
	 * Gets the scope for this frame
	 */
	void scope() {
		CFRequestPacket request = new CFRequestPacket(Commands.SCOPE, thread.id());
		request.setArgument(Attributes.FRAME_NUMBER, new Integer(index));
		request.setArgument(Attributes.NUMBER, new Integer(0));
		CFResponsePacket response = crossfire().sendRequest(request);
		if(response.isSuccess()) {
			Scope s = new Scope(
					(Number)response.getBody().get(Attributes.INDEX), 
					(Number)response.getBody().get(Attributes.FRAME_INDEX),
					(Number) ((Map)response.getBody().get(Attributes.OBJECT)).get(Attributes.HANDLE));
			scopes.add(s);
		}
		else if(TRACE) {
			Tracing.writeString("VM [failed scopes request]: "+JSON.serialize(request)); //$NON-NLS-1$
		}
	}
}
