/*******************************************************************************
 * Copyright (c) 2000, 2015 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.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.Iterator;
import java.util.List;

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.ArrayReference;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.InternalException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.Mirror;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.Type;
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 ArrayReferenceImpl extends ObjectReferenceImpl implements
		ArrayReference {
	/** JDWP Tag. */
	public static final byte tag = JdwpID.ARRAY_TAG;

	private int fLength = -1;

	/**
	 * Creates new ArrayReferenceImpl.
	 * @param vmImpl the VM
	 * @param objectID the object ID
	 */
	public ArrayReferenceImpl(VirtualMachineImpl vmImpl, JdwpObjectID objectID) {
		super("ArrayReference", vmImpl, objectID); //$NON-NLS-1$
	}

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

	/**
	 * Returns the {@link Value} from the given index
	 * @param index the index
	 * @return the {@link Value} at the given index
	 * @throws IndexOutOfBoundsException if the index is outside the bounds of the array
	 * @returns Returns an array component value.
	 */
	@Override
	public Value getValue(int index) throws IndexOutOfBoundsException {
		return getValues(index, 1).get(0);
	}

	/**
	 * @return all of the components in this array.
	 */
	@Override
	public List<Value> getValues() {
		return getValues(0, -1);
	}

	/**
	 * Gets all of the values starting at firstIndex and ending at firstIndex+length
	 *
	 * @param firstIndex the start
	 * @param length the  number of values to return
	 * @return the list of {@link Value}s
	 * @throws IndexOutOfBoundsException if the index is outside the bounds of the array
	 * @returns Returns a range of array components.
	 */
	@Override
	public List<Value> getValues(int firstIndex, int length)
			throws IndexOutOfBoundsException {

		int arrayLength = length();

		if (firstIndex < 0 || firstIndex >= arrayLength) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Invalid_index_1);
		}

		if (length == -1) {
			// length == -1 means all elements to the end.
			length = arrayLength - firstIndex;
		} else if (length < -1) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Invalid_number_of_value_to_get_from_array_1);
		} else if (firstIndex + length > arrayLength) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Attempted_to_get_more_values_from_array_than_length_of_array_2);
		}

		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData); // arrayObject
			writeInt(firstIndex, "firstIndex", outData); //$NON-NLS-1$
			writeInt(length, "length", outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.AR_GET_VALUES, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_INDEX:
				throw new IndexOutOfBoundsException(
						JDIMessages.ArrayReferenceImpl_Invalid_index_of_array_reference_given_1);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();

			/*
			 * NOTE: The JDWP documentation is not clear on this: it turns out
			 * that the following is received from the VM: - type tag; - length
			 * of array; - values of elements.
			 */

			int type = readByte("type", JdwpID.tagMap(), replyData); //$NON-NLS-1$
			int readLength = readInt("length", replyData); //$NON-NLS-1$
			// See also ValueImpl.
			switch (type) {
			// Multidimensional array.
			case ArrayReferenceImpl.tag:
				// Object references.
			case ClassLoaderReferenceImpl.tag:
			case ClassObjectReferenceImpl.tag:
			case StringReferenceImpl.tag:
			case ObjectReferenceImpl.tag:
			case ThreadGroupReferenceImpl.tag:
			case ThreadReferenceImpl.tag:
				return readObjectSequence(readLength, replyData);

				// Primitive type.
			case BooleanValueImpl.tag:
			case ByteValueImpl.tag:
			case CharValueImpl.tag:
			case DoubleValueImpl.tag:
			case FloatValueImpl.tag:
			case IntegerValueImpl.tag:
			case LongValueImpl.tag:
			case ShortValueImpl.tag:
				return readPrimitiveSequence(readLength, type, replyData);

			case VoidValueImpl.tag:
			case 0:
			default:
				throw new InternalException(
						JDIMessages.ArrayReferenceImpl_Invalid_ArrayReference_Value_tag_encountered___2
								+ type);
			}
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Reads the given length of objects from the given stream
	 * @param length the number of objects to read
	 * @param in the stream to read from
	 * @return the {@link List} of {@link ValueImpl}s
	 * @throws IOException if the reading fails
	 * @returns Returns sequence of object reference values.
	 */
	private List<Value> readObjectSequence(int length, DataInputStream in)
			throws IOException {
		List<Value> elements = new ArrayList<>(length);
		for (int i = 0; i < length; i++) {
			ValueImpl value = ObjectReferenceImpl
					.readObjectRefWithTag(this, in);
			elements.add(value);
		}
		return elements;
	}

	/**
	 * @param length
	 *            the number of primitives to read
	 * @param type
	 *            the type
	 * @param in
	 *            the input stream
	 * @return Returns sequence of values of primitive type.
	 * @throws IOException
	 *             if reading from the stream encounters a problem
	 */
	private List<Value> readPrimitiveSequence(int length, int type, DataInputStream in)
			throws IOException {
		List<Value> elements = new ArrayList<>(length);
		for (int i = 0; i < length; i++) {
			ValueImpl value = ValueImpl.readWithoutTag(this, type, in);
			elements.add(value);
		}
		return elements;
	}

	/**
	 * @return Returns the number of components in this array.
	 */
	@Override
	public int length() {
		if (fLength == -1) {
			initJdwpRequest();
			try {
				JdwpReplyPacket replyPacket = requestVM(
						JdwpCommandPacket.AR_LENGTH, this);
				defaultReplyErrorHandler(replyPacket.errorCode());
				DataInputStream replyData = replyPacket.dataInStream();
				fLength = readInt("length", replyData); //$NON-NLS-1$
			} catch (IOException e) {
				defaultIOExceptionHandler(e);
				return 0;
			} finally {
				handledJdwpRequest();
			}
		}
		return fLength;
	}

	/**
	 * Replaces an array component with another value.
	 *
	 * @param index
	 *            the index to set the value in
	 * @param value
	 *            the new value
	 * @throws InvalidTypeException
	 *             thrown if the types of the replacements do not match the
	 *             underlying type of the {@link ArrayReference}
	 * @throws ClassNotLoadedException
	 *             thrown if the class type for the {@link ArrayReference} is
	 *             not loaded or has been GC'd
	 * @see #setValues(int, List, int, int)
	 */
	@Override
	public void setValue(int index, Value value) throws InvalidTypeException,
			ClassNotLoadedException {
		ArrayList<Value> list = new ArrayList<>(1);
		list.add(value);
		setValues(index, list, 0, 1);
	}

	/**
	 * Replaces all array components with other values.
	 *
	 * @param values
	 *            the new values to set in the array
	 * @throws InvalidTypeException
	 *             thrown if the types of the replacements do not match the
	 *             underlying type of the {@link ArrayReference}
	 * @throws ClassNotLoadedException
	 *             thrown if the class type for the {@link ArrayReference} is
	 *             not loaded or has been GC'd
	 * @see #setValues(int, List, int, int)
	 */
	@Override
	public void setValues(List<? extends Value> values) throws InvalidTypeException,
			ClassNotLoadedException {
		setValues(0, values, 0, -1);
	}

	/**
	 * Replaces a range of array components with other values.
	 *
	 * @param index
	 *            offset in this array to start replacing values at
	 * @param values
	 *            replacement values
	 * @param srcIndex
	 *            the first offset where values are copied from the given
	 *            replacement values
	 * @param length
	 *            the number of values to replace in this array
	 * @throws InvalidTypeException
	 *             thrown if the types of the replacements do not match the
	 *             underlying type of the {@link ArrayReference}
	 * @throws ClassNotLoadedException
	 *             thrown if the class type for the {@link ArrayReference} is
	 *             not loaded or has been GC'd
	 */
	@Override
	public void setValues(int index, List<? extends Value> values, int srcIndex, int length)
			throws InvalidTypeException, ClassNotLoadedException {
		if (values == null || values.size() == 0) {
			// trying to set nothing should do no work
			return;
		}
		int valuesSize = values.size();
		int arrayLength = length();

		if (index < 0 || index >= arrayLength) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Invalid_index_1);
		}
		if (srcIndex < 0 || srcIndex >= valuesSize) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Invalid_srcIndex_2);
		}

		if (length < -1) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Invalid_number_of_value_to_set_in_array_3);
		} else if (length == -1) {
			// length == -1 indicates as much values as possible.
			length = arrayLength - index;
			int lengthTmp = valuesSize - srcIndex;
			if (lengthTmp < length) {
				length = lengthTmp;
			}
		} else if (index + length > arrayLength) {
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Attempted_to_set_more_values_in_array_than_length_of_array_3);
		} else if (srcIndex + length > valuesSize) {
			// Check if enough values are given.
			throw new IndexOutOfBoundsException(
					JDIMessages.ArrayReferenceImpl_Attempted_to_set_more_values_in_array_than_given_4);
		}

		// check and convert the values if needed.
		List<Value> checkedValues = checkValues(
				values.subList(srcIndex, srcIndex + length),
				((ArrayTypeImpl) referenceType()).componentType());

		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			writeInt(index, "index", outData); //$NON-NLS-1$
			writeInt(length, "length", outData); //$NON-NLS-1$
			Iterator<Value> iterValues = checkedValues.iterator();
			while (iterValues.hasNext()) {
				ValueImpl value = (ValueImpl) iterValues.next();
				if (value != null) {
					value.write(this, outData);
				} else {
					ValueImpl.writeNull(this, outData);
				}
			}

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

	/**
	 * Check the type and the VM of the values. If the given type is a primitive
	 * type, the values may be converted to match this type.
	 *
	 * @param values
	 *            the value(s) to check
	 * @param type
	 *            the type to compare the values to
	 * @return the list of values converted to the given type
	 * @throws InvalidTypeException
	 *             if the underlying type of an object in the list is not
	 *             compatible
	 *
	 * @see ValueImpl#checkValue(Value, Type, VirtualMachineImpl)
	 */
	private List<Value> checkValues(List<? extends Value> values, Type type)
			throws InvalidTypeException {
		List<Value> checkedValues = new ArrayList<>(values.size());
		Iterator<? extends Value> iterValues = values.iterator();
		while (iterValues.hasNext()) {
			checkedValues.add(ValueImpl.checkValue(iterValues.next(),
					type, virtualMachineImpl()));
		}
		return checkedValues;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.jdi.internal.ObjectReferenceImpl#toString()
	 */
	@Override
	public String toString() {
		try {
			StringBuffer buf = new StringBuffer(type().name());
			// Insert length of string between (last) square braces.
			buf.insert(buf.length() - 1, length());
			// Append space and idString.
			buf.append(' ');
			buf.append(idString());
			return buf.toString();
		} catch (ObjectCollectedException e) {
			return JDIMessages.ArrayReferenceImpl__Garbage_Collected__ArrayReference_5
					+ "[" + length() + "] " + idString(); //$NON-NLS-1$ //$NON-NLS-2$
		} catch (Exception e) {
			return fDescription;
		}
	}

	/**
	 * Reads JDWP representation and returns new instance.
	 *
	 * @param target
	 *            the target {@link Mirror} object
	 * @param in
	 *            the input stream to read from
	 * @return Reads JDWP representation and returns new instance.
	 * @throws IOException
	 *             if there is a problem reading from the stream
	 */
	public static ArrayReferenceImpl read(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("arrayReference", ID.value()); //$NON-NLS-1$
		}

		if (ID.isNull()) {
			return null;
		}

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