/*******************************************************************************
 * 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.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpObjectID;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;

import com.sun.jdi.ArrayType;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.Field;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InternalException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Method;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Type;
import com.sun.jdi.VMDisconnectedException;
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 ObjectReferenceImpl extends ValueImpl implements ObjectReference {
	/** JDWP Tag. */
	public static final byte tag = JdwpID.OBJECT_TAG;

	/** ObjectID of object that corresponds to this reference. */
	private JdwpObjectID fObjectID;
	/**
	 * Cached reference type. This value is safe for caching because the type of
	 * an object never changes.
	 */
	private ReferenceType fReferenceType;

	/**
	 * Creates new ObjectReferenceImpl.
	 */
	public ObjectReferenceImpl(VirtualMachineImpl vmImpl, JdwpObjectID objectID) {
		this("ObjectReference", vmImpl, objectID); //$NON-NLS-1$
	}

	/**
	 * Creates new ObjectReferenceImpl.
	 */
	public ObjectReferenceImpl(String description, VirtualMachineImpl vmImpl,
			JdwpObjectID objectID) {
		super(description, vmImpl);
		fObjectID = objectID;
	}

	/**
	 * @returns tag.
	 */
	@Override
	public byte getTag() {
		return tag;
	}

	/**
	 * @return Returns Jdwp Object ID.
	 */
	public JdwpObjectID getObjectID() {
		return fObjectID;
	}

	/**
	 * Prevents garbage collection for this object.
	 */
	@Override
	public void disableCollection() {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_DISABLE_COLLECTION, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Permits garbage collection for this object.
	 */
	@Override
	public void enableCollection() {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_ENABLE_COLLECTION, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Inner class used to return monitor info.
	 */
	private static class MonitorInfo {
		ThreadReferenceImpl owner;
		int entryCount;
		ArrayList<ThreadReference> waiters;
	}

	/**
	 * @return Returns monitor info.
	 */
	private MonitorInfo monitorInfo() throws IncompatibleThreadStateException {
		if (!virtualMachine().canGetMonitorInfo()) {
			throw new UnsupportedOperationException();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_MONITOR_INFO, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_THREAD:
				throw new IncompatibleThreadStateException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException();
			}

			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			MonitorInfo result = new MonitorInfo();
			result.owner = ThreadReferenceImpl.read(this, replyData);
			result.entryCount = readInt("entry count", replyData); //$NON-NLS-1$
			int nrOfWaiters = readInt("nr of waiters", replyData); //$NON-NLS-1$
			result.waiters = new ArrayList<>(nrOfWaiters);
			for (int i = 0; i < nrOfWaiters; i++)
				result.waiters.add(ThreadReferenceImpl.read(this, replyData));
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns an ThreadReference for the thread, if any, which
	 *         currently owns this object's monitor.
	 */
	@Override
	public ThreadReference owningThread()
			throws IncompatibleThreadStateException {
		return monitorInfo().owner;
	}

	/**
	 * @return Returns the number times this object's monitor has been entered
	 *         by the current owning thread.
	 */
	@Override
	public int entryCount() throws IncompatibleThreadStateException {
		return monitorInfo().entryCount;
	}

	/**
	 * @return Returns a List containing a ThreadReference for each thread
	 *         currently waiting for this object's monitor.
	 */
	@Override
	public List<ThreadReference> waitingThreads() throws IncompatibleThreadStateException {
		return monitorInfo().waiters;
	}

	/**
	 * @return Returns the value of a given instance or static field in this
	 *         object.
	 */
	@Override
	public Value getValue(Field field) {
		ArrayList<Field> list = new ArrayList<>(1);
		list.add(field);
		return getValues(list).get(field);
	}

	/**
	 * @return Returns objects that directly reference this object. Only objects
	 *         that are reachable for the purposes of garbage collection are
	 *         returned. Note that an object can also be referenced in other
	 *         ways, such as from a local variable in a stack frame, or from a
	 *         JNI global reference. Such non-object referrers are not returned
	 *         by this method.
	 *
	 * @since 3.3
	 */
	@Override
	public List<ObjectReference> referringObjects(long maxReferrers)
			throws UnsupportedOperationException, IllegalArgumentException {
		try {
			int max = (int) maxReferrers;
			if (maxReferrers >= Integer.MAX_VALUE) {
				max = Integer.MAX_VALUE;
			}
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			this.getObjectID().write(outData);
			writeInt(max, "max referrers", outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_REFERRING_OBJECTS, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_27);
			case JdwpReplyPacket.ILLEGAL_ARGUMENT:
				throw new IllegalArgumentException(
						JDIMessages.ReferenceTypeImpl_26);
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.ObjectReferenceImpl_object_not_known);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int elements = readInt("elements", replyData); //$NON-NLS-1$
			if (max > 0 && elements > max) {
				elements = max;
			}
			ArrayList<ObjectReference> list = new ArrayList<>();
			for (int i = 0; i < elements; i++) {
				list.add((ObjectReference)ValueImpl.readWithTag(this, replyData));
			}
			return list;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the value of multiple instance and/or static fields in
	 *         this object.
	 */
	@Override
	public Map<Field, Value> getValues(List<? extends Field> allFields) {
		// if the field list is empty, nothing to do.
		if (allFields.isEmpty()) {
			return new HashMap<>();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);

			/*
			 * Distinguish static fields from non-static fields: For static
			 * fields ReferenceTypeImpl.getValues() must be used.
			 */
			List<Field> staticFields = new ArrayList<>();
			List<FieldImpl> nonStaticFields = new ArrayList<>();

			// Separate static and non-static fields.
			int allFieldsSize = allFields.size();
			for (int i = 0; i < allFieldsSize; i++) {
				FieldImpl field = (FieldImpl) allFields.get(i);
				checkVM(field);
				if (field.isStatic())
					staticFields.add(field);
				else
					nonStaticFields.add(field);
			}

			// First get values for the static fields.
			Map<Field, Value> resultMap;
			if (staticFields.isEmpty()) {
				resultMap = new HashMap<>();
			} else {
				resultMap = referenceType().getValues(staticFields);
			}

			// if no non-static fields are requested, return directly the
			// result.
			if (nonStaticFields.isEmpty()) {
				return resultMap;
			}
			// Then get the values for the non-static fields.
			int nonStaticFieldsSize = nonStaticFields.size();
			write(this, outData);
			writeInt(nonStaticFieldsSize, "size", outData); //$NON-NLS-1$
			for (int i = 0; i < nonStaticFieldsSize; i++) {
				FieldImpl field = nonStaticFields.get(i);
				field.write(this, outData);
			}

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

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

			for (int i = 0; i < nrOfElements; i++) {
				resultMap.put(nonStaticFields.get(i),
						ValueImpl.readWithTag(this, replyData));
			}
			return resultMap;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the hash code value.
	 */
	@Override
	public int hashCode() {
		return fObjectID.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())
				&& fObjectID.equals(((ObjectReferenceImpl) object).fObjectID)
				&& virtualMachine().equals(
						((MirrorImpl) object).virtualMachine());
	}

	/**
	 * @return Returns Jdwp version of given options.
	 */
	private int optionsToJdwpOptions(int options) {
		int jdwpOptions = 0;
		if ((options & INVOKE_SINGLE_THREADED) != 0) {
			jdwpOptions |= MethodImpl.INVOKE_SINGLE_THREADED_JDWP;
		}
		if ((options & INVOKE_NONVIRTUAL) != 0) {
			jdwpOptions |= MethodImpl.INVOKE_NONVIRTUAL_JDWP;
		}
		return jdwpOptions;
	}

	/**
	 * Invokes the specified static Method in the target VM.
	 *
	 * @return Returns a Value mirror of the invoked method's return value.
	 */
	@Override
	public Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options) throws InvalidTypeException,
			ClassNotLoadedException, IncompatibleThreadStateException,
			InvocationException {
		checkVM(thread);
		checkVM(method);
		ThreadReferenceImpl threadImpl = (ThreadReferenceImpl) thread;
		MethodImpl methodImpl = (MethodImpl) method;

		// Perform some checks for IllegalArgumentException.
		if (!isAValidMethod(method))
			throw new IllegalArgumentException(
					JDIMessages.ObjectReferenceImpl_Class_does_not_contain_given_method_2);
		if (method.argumentTypeNames().size() != arguments.size())
			throw new IllegalArgumentException(
					JDIMessages.ObjectReferenceImpl_Number_of_arguments_doesn__t_match_3);
		if (method.isConstructor() || method.isStaticInitializer())
			throw new IllegalArgumentException(
					JDIMessages.ObjectReferenceImpl_Method_is_constructor_or_intitializer_4);
		if ((options & INVOKE_NONVIRTUAL) != 0 && method.isAbstract())
			throw new IllegalArgumentException(
					JDIMessages.ObjectReferenceImpl_Method_is_abstract_and_can_therefore_not_be_invoked_nonvirtual_5);

		// check the type and the vm of the argument, convert the value if
		// needed.
		List<Value> checkedArguments = ValueImpl.checkValues(arguments,	method.argumentTypes(), virtualMachineImpl());

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			threadImpl.write(this, outData);
			((ReferenceTypeImpl) referenceType()).write(this, outData);
			methodImpl.write(this, outData);

			writeInt(checkedArguments.size(), "size", outData); //$NON-NLS-1$
			Iterator<Value> iter = checkedArguments.iterator();
			while (iter.hasNext()) {
				ValueImpl elt = (ValueImpl) iter.next();
				if (elt != null) {
					elt.writeWithTag(this, outData);
				} else {
					ValueImpl.writeNullWithTag(this, outData);
				}
			}

			writeInt(optionsToJdwpOptions(options),
					"options", MethodImpl.getInvokeOptions(), outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_INVOKE_METHOD, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.TYPE_MISMATCH:
				throw new InvalidTypeException();
			case JdwpReplyPacket.INVALID_CLASS:
				throw new ClassNotLoadedException(
						JDIMessages.ObjectReferenceImpl_One_of_the_arguments_of_ObjectReference_invokeMethod___6);
			case JdwpReplyPacket.INVALID_THREAD:
				throw new IncompatibleThreadStateException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException();
			case JdwpReplyPacket.INVALID_TYPESTATE:
				throw new IncompatibleThreadStateException();
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			ValueImpl value = ValueImpl.readWithTag(this, replyData);
			ObjectReferenceImpl exception = ObjectReferenceImpl
					.readObjectRefWithTag(this, replyData);
			if (exception != null)
				throw new InvocationException(exception);
			return value;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	private boolean isAValidMethod(Method method) {
		ReferenceType refType = referenceType();
		if (refType instanceof ArrayType) {
			// if the object is an array, check if the method is declared in
			// java.lang.Object
			return "java.lang.Object".equals(method.declaringType().name()); //$NON-NLS-1$
		}
		return refType.allMethods().contains(method);
	}

	/**
	 * @return Returns if this object has been garbage collected in the target
	 *         VM.
	 */
	@Override
	public boolean isCollected() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_IS_COLLECTED, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_OBJECT:
				return true;
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				// Workaround for problem in J2ME WTK (wireless toolkit)
				// @see Bug 12966
				try {
					referenceType();
				} catch (ObjectCollectedException e) {
					return true;
				}
				return false;
			default:
				defaultReplyErrorHandler(replyPacket.errorCode());
				break;
			}
			DataInputStream replyData = replyPacket.dataInStream();
			boolean result = readBoolean("is collected", replyData); //$NON-NLS-1$
			return result;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return false;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the ReferenceType that mirrors the type of this object.
	 */
	@Override
	public ReferenceType referenceType() {
		if (fReferenceType != null) {
			return fReferenceType;
		}
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_REFERENCE_TYPE, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fReferenceType = ReferenceTypeImpl.readWithTypeTag(this, replyData);
			return fReferenceType;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the Type that mirrors the type of this object.
	 */
	@Override
	public Type type() {
		return referenceType();
	}

	/**
	 * Sets the value of a given instance or static field in this object.
	 */
	@Override
	public void setValue(Field field, Value value) throws InvalidTypeException,
			ClassNotLoadedException {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			writeInt(1, "size", outData); // We only set one field //$NON-NLS-1$
			checkVM(field);
			((FieldImpl) field).write(this, outData);

			// check the type and the vm of the value. Convert the value if
			// needed
			ValueImpl checkedValue = ValueImpl.checkValue(value, field.type(),
					virtualMachineImpl());

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

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.OR_SET_VALUES, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.TYPE_MISMATCH:
				throw new InvalidTypeException();
			case JdwpReplyPacket.INVALID_CLASS:
				throw new ClassNotLoadedException(referenceType().name());
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns a unique identifier for this ObjectReference.
	 */
	@Override
	public long uniqueID() {
		return fObjectID.value();
	}

	/**
	 * @return Returns string with value of ID.
	 */
	public String idString() {
		return "(id=" + fObjectID + ")"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * @return Returns description of Mirror object.
	 */
	@Override
	public String toString() {
		try {
			return type().toString() + " " + idString(); //$NON-NLS-1$
		} catch (ObjectCollectedException e) {
			return JDIMessages.ObjectReferenceImpl__Garbage_Collected__ObjectReference__8
					+ idString();
		} catch (Exception e) {
			return fDescription;
		}
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	public static ObjectReferenceImpl readObjectRefWithoutTag(
			MirrorImpl target, DataInputStream in) throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpObjectID ID = new JdwpObjectID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println("objectReference", ID.value()); //$NON-NLS-1$

		if (ID.isNull())
			return null;

		ObjectReferenceImpl mirror = new ObjectReferenceImpl(vmImpl, ID);
		return mirror;
	}

	/**
	 * @return Reads JDWP representation and returns new instance.
	 */
	public static ObjectReferenceImpl readObjectRefWithTag(MirrorImpl target,
			DataInputStream in) throws IOException {
		byte objectTag = target.readByte("object tag", JdwpID.tagMap(), in); //$NON-NLS-1$
		switch (objectTag) {
		case 0:
			return null;
		case ObjectReferenceImpl.tag:
			return ObjectReferenceImpl.readObjectRefWithoutTag(target, in);
		case ArrayReferenceImpl.tag:
			return ArrayReferenceImpl.read(target, in);
		case ClassLoaderReferenceImpl.tag:
			return ClassLoaderReferenceImpl.read(target, in);
		case ClassObjectReferenceImpl.tag:
			return ClassObjectReferenceImpl.read(target, in);
		case StringReferenceImpl.tag:
			return StringReferenceImpl.read(target, in);
		case ThreadGroupReferenceImpl.tag:
			return ThreadGroupReferenceImpl.read(target, in);
		case ThreadReferenceImpl.tag:
			return ThreadReferenceImpl.read(target, in);
		}
		throw new InternalException(
				JDIMessages.ObjectReferenceImpl_Invalid_ObjectID_tag_encountered___9
						+ objectTag);
	}

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