/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdi.internal;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpFrameID;
import org.eclipse.jdi.internal.jdwp.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;

import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.InvalidStackFrameException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Locatable;
import com.sun.jdi.Location;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMMismatchException;
import com.sun.jdi.Value;

/**
 * this class implements the corresponding interfaces declared by the JDI
 * specification. See the com.sun.jdi package for more information.
 *
 */
public class StackFrameImpl extends MirrorImpl implements StackFrame, Locatable {
	/** FrameID that corresponds to this reference. */
	private JdwpFrameID fFrameID;
	/** Thread under which this frame's method is running. */
	private ThreadReferenceImpl fThread;
	/** Location of the current instruction in the frame. */
	private LocationImpl fLocation;

	/**
	 * Creates new StackFrameImpl.
	 */
	public StackFrameImpl(VirtualMachineImpl vmImpl, JdwpFrameID ID,
			ThreadReferenceImpl thread, LocationImpl location) {
		super("StackFrame", vmImpl); //$NON-NLS-1$
		fFrameID = ID;
		fThread = thread;
		fLocation = location;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#getValue(com.sun.jdi.LocalVariable)
	 */
	@Override
	public Value getValue(LocalVariable variable)
			throws IllegalArgumentException, InvalidStackFrameException,
			VMMismatchException {
		ArrayList<LocalVariable> list = new ArrayList<>(1);
		list.add(variable);
		return getValues(list).get(variable);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#getValues(java.util.List)
	 */
	@Override
	public Map<LocalVariable, Value> getValues(List<? extends LocalVariable> variables) throws IllegalArgumentException,
			InvalidStackFrameException, VMMismatchException {
		// Note that this information should not be cached.
		Map<LocalVariable, Value> map = new HashMap<>(variables.size());
		// if the variable list is empty, nothing to do
		if (variables.isEmpty()) {
			return map;
		}
		/*
		 * If 'this' is requested, we have to use a special JDWP request.
		 * Therefore, we remember the positions in the list of requests for
		 * 'this'.
		 */
		int sizeAll = variables.size();
		int sizeThis = 0;
		boolean[] isThisValue = new boolean[sizeAll];
		for (int i = 0; i < sizeAll; i++) {
			LocalVariableImpl var = (LocalVariableImpl) variables.get(i);
			isThisValue[i] = var.isThis();
			if (isThisValue[i]) {
				sizeThis++;
			}
		}
		int sizeNotThis = sizeAll - sizeThis;

		if (sizeThis > 0) {
			Value thisValue = thisObject();
			for (int i = 0; i < sizeAll; i++) {
				if (isThisValue[i]) {
					map.put(variables.get(i), thisValue);
				}
			}
		}

		// If only 'this' was requested, we're finished.
		if (sizeNotThis == 0) {
			return map;
		}

		// Request values for local variables other than 'this'.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			writeWithThread(this, outData);
			writeInt(sizeNotThis, "size", outData); //$NON-NLS-1$
			for (int i = 0; i < sizeAll; i++) {
				if (!isThisValue[i]) {
					LocalVariableImpl var = (LocalVariableImpl) variables
							.get(i);
					checkVM(var);
					writeInt(var.slot(), "slot", outData); //$NON-NLS-1$
					writeByte(var.tag(), "tag", JdwpID.tagMap(), outData); //$NON-NLS-1$
				}
			}
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.SF_GET_VALUES, outBytes);
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			if (nrOfElements != sizeNotThis)
				throw new InternalError(
						JDIMessages.StackFrameImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_1);

			for (int i = 0, j = 0; i < sizeAll; i++) {
				if (!isThisValue[i])
					map.put(variables.get(j++),
							ValueImpl.readWithTag(this, replyData));
			}
			return map;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#getArgumentValues()
	 */
	@Override
	public List<Value> getArgumentValues() throws InvalidStackFrameException {
		if (!thread().isSuspended()) {
			throw new InvalidStackFrameException(
					JDIMessages.StackFrameImpl_no_argument_values_available);
		}
		try {
			List<LocalVariable> list = location().method().variables();
			ArrayList<Value> ret = new ArrayList<>();
			LocalVariable var = null;
			for (Iterator<LocalVariable> iter = list.iterator(); iter.hasNext();) {
				var = iter.next();
				if (var.isArgument()) {
					ret.add(getValue(var));
				}
			}
			return ret;
		} catch (AbsentInformationException e) {
			JDIDebugPlugin.log(e);
			return null;
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#location()
	 */
	@Override
	public Location location() {
		return fLocation;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#setValue(com.sun.jdi.LocalVariable, com.sun.jdi.Value)
	 */
	@Override
	public void setValue(LocalVariable var, Value value)
			throws InvalidTypeException, ClassNotLoadedException {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			((ThreadReferenceImpl) thread()).write(this, outData);
			write(this, outData);
			writeInt(1, "size", outData); // We only set one field //$NON-NLS-1$
			checkVM(var);
			writeInt(((LocalVariableImpl) var).slot(), "slot", outData); //$NON-NLS-1$

			// check the type and the VM of the value, convert the value if
			// needed.
			ValueImpl checkedValue = ValueImpl.checkValue(value, var.type(),
					virtualMachineImpl());

			if (checkedValue != null) {
				checkedValue.writeWithTag(this, outData);
			} else {
				ValueImpl.writeNullWithTag(this, outData);
			}

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.SF_SET_VALUES, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_CLASS:
				throw new ClassNotLoadedException(var.typeName());
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#thisObject()
	 */
	@Override
	public ObjectReference thisObject() throws InvalidStackFrameException {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			writeWithThread(this, outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.SF_THIS_OBJECT, outBytes);
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			ObjectReference result = ObjectReferenceImpl.readObjectRefWithTag(
					this, replyData);
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#thread()
	 */
	@Override
	public ThreadReference thread() {
		return fThread;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#visibleVariableByName(java.lang.String)
	 */
	@Override
	public LocalVariable visibleVariableByName(String name)
			throws AbsentInformationException {
		Iterator<LocalVariable> iter = visibleVariables().iterator();
		while (iter.hasNext()) {
			LocalVariableImpl var = (LocalVariableImpl) iter.next();
			if (var.name().equals(name)) {
				return var;
			}
		}

		return null;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.StackFrame#visibleVariables()
	 */
	@Override
	public List<LocalVariable> visibleVariables() throws AbsentInformationException {
		List<LocalVariable> variables = fLocation.method().variables();
		Iterator<LocalVariable> iter = variables.iterator();
		List<LocalVariable> visibleVars = new ArrayList<>(variables.size());
		while (iter.hasNext()) {
			LocalVariableImpl var = (LocalVariableImpl) iter.next();
			// Only return local variables other than the this pointer.
			if (var.isVisible(this) && !var.isThis()) {
				visibleVars.add(var);
			}
		}
		return visibleVars;
	}

	/**
	 * @return Returns the hash code value.
	 */
	@Override
	public int hashCode() {
		return fThread.hashCode() + fFrameID.hashCode();
	}

	/**
	 * @return Returns true if two mirrors refer to the same entity in the
	 *         target VM.
	 * @see java.lang.Object#equals(Object)
	 */
	@Override
	public boolean equals(Object object) {
		return object != null && object.getClass().equals(this.getClass())
				&& fThread.equals(((StackFrameImpl) object).fThread)
				&& fFrameID.equals(((StackFrameImpl) object).fFrameID);
	}

	/**
	 * Writes JDWP representation.
	 */
	public void write(MirrorImpl target, DataOutputStream out)
			throws IOException {
		fFrameID.write(out);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("stackFrame", fFrameID.value()); //$NON-NLS-1$
		}
	}

	/**
	 * Writes JDWP representation.
	 */
	public void writeWithThread(MirrorImpl target, DataOutputStream out)
			throws IOException {
		fThread.write(target, out);
		write(target, out);
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	public static StackFrameImpl readWithLocation(MirrorImpl target,
			ThreadReferenceImpl thread, DataInputStream in) throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpFrameID ID = new JdwpFrameID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("stackFrame", ID.value()); //$NON-NLS-1$
		}

		if (ID.isNull()) {
			return null;
		}
		LocationImpl location = LocationImpl.read(target, in);
		if (location == null) {
			return null;
		}

		return new StackFrameImpl(vmImpl, ID, thread, location);
	}
}
