/*******************************************************************************
 * 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
 *     Jesper Steen Møller <jesper@selskabet.org> - Bug 430839
 *******************************************************************************/
package org.eclipse.jdi.internal;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jdi.internal.jdwp.JdwpClassObjectID;
import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpInterfaceID;

import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassNotPreparedException;
import com.sun.jdi.ClassType;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Method;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
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 InterfaceTypeImpl extends ReferenceTypeImpl implements
		InterfaceType {
	/** JDWP Tag. */
	public static final byte typeTag = JdwpID.TYPE_TAG_INTERFACE;

	/**
	 * Creates new InterfaceTypeImpl.
	 */
	public InterfaceTypeImpl(VirtualMachineImpl vmImpl,
			JdwpInterfaceID interfaceID) {
		super("InterfaceType", vmImpl, interfaceID); //$NON-NLS-1$
	}

	/**
	 * Creates new InterfaceTypeImpl.
	 */
	public InterfaceTypeImpl(VirtualMachineImpl vmImpl,
			JdwpInterfaceID interfaceID, String signature,
			String genericSignature) {
		super("InterfaceType", vmImpl, interfaceID, signature, genericSignature); //$NON-NLS-1$
	}

	/**
	 * @return Create a null value instance of the type.
	 */
	@Override
	public Value createNullValue() {
		return new ClassObjectReferenceImpl(virtualMachineImpl(),
				new JdwpClassObjectID(virtualMachineImpl()));
	}

	/**
	 * @return Returns type tag.
	 */
	@Override
	public byte typeTag() {
		return typeTag;
	}

	/**
	 * Flushes all stored Jdwp results.
	 */
	@Override
	public void flushStoredJdwpResults() {
		super.flushStoredJdwpResults();

		// For all reference types that have this interface cached, this cache must be
		// undone.
		Iterator<Object> itr = virtualMachineImpl().allCachedRefTypes();
		while (itr.hasNext()) {
			ReferenceTypeImpl refType = (ReferenceTypeImpl) itr.next();
			if (refType.fInterfaces != null
					&& refType.fInterfaces.contains(this)) {
				refType.flushStoredJdwpResults();
			}
		}

	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.InterfaceType#implementors()
	 */
	@Override
	public List<ClassType> implementors() {
		// Note that this information should not be cached.
		List<ClassType> implementors = new ArrayList<ClassType>();
		Iterator<ReferenceType> itr = virtualMachineImpl().allRefTypes();
		while (itr.hasNext()) {
			ReferenceType refType = itr.next();
			if (refType instanceof ClassTypeImpl) {
				try {
					ClassTypeImpl classType = (ClassTypeImpl) refType;
					List<InterfaceType> interfaces = classType.interfaces();
					if (interfaces.contains(this)) {
						implementors.add(classType);
					}
				} catch (ClassNotPreparedException e) {
					continue;
				}
			}
		}
		return implementors;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.InterfaceType#subinterfaces()
	 */
	@Override
	public List<InterfaceType> subinterfaces() {
		// Note that this information should not be cached.
		List<InterfaceType> implementors = new ArrayList<InterfaceType>();
		Iterator<ReferenceType> itr = virtualMachineImpl().allRefTypes();
		while (itr.hasNext()) {
			try {
				ReferenceType refType = itr.next();
				if (refType instanceof InterfaceTypeImpl) {
					InterfaceTypeImpl interFaceType = (InterfaceTypeImpl) refType;
					List<InterfaceType> interfaces = interFaceType.superinterfaces();
					if (interfaces.contains(this)) {
						implementors.add(interFaceType);
					}
				}
			} catch (ClassNotPreparedException e) {
				continue;
			}
		}
		return implementors;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.InterfaceType#superinterfaces()
	 */
	@Override
	public List<InterfaceType> superinterfaces() {
		return interfaces();
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.InterfaceType#invokeMethod(com.sun.jdi.ThreadReference, com.sun.jdi.Method, java.util.List, int)
	 */
	@Override
	public Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options) throws InvalidTypeException,
			ClassNotLoadedException, IncompatibleThreadStateException,
			InvocationException {
		return invokeMethod(thread, method, arguments, options, JdwpCommandPacket.IT_INVOKE_METHOD);
	}

	/**
	 * @return Returns a the single non-abstract Method visible from this class
	 *         that has the given name and signature.
	 */
	public Method concreteMethodByName(String name, String signature) {
		/*
		 * Recursion is used to find the method: The methods of its own (own
		 * methods() command); The methods of it's superclass.
		 */

		Iterator<Method> methods = methods().iterator();
		Method method;
		while (methods.hasNext()) {
			method = methods.next();
			if (method.name().equals(name) && method.signature().equals(signature)) {
				if (method.isAbstract()) {
					return null;
				}
				return method;
			}
		}

		if (superinterfaces() != null) {
			for (InterfaceType superi: superinterfaces()) {
				Method foundMethod = ((InterfaceTypeImpl)superi).concreteMethodByName(name, signature);
				if (foundMethod != null) {
					return foundMethod;
				}
			}
		}

		return null;
	}

	
	/**
	 * @return Returns true if this type has been initialized.
	 */
	@Override
	public boolean isInitialized() {
		return isPrepared();
	}

	/**
	 * @return Reads ID and returns known ReferenceTypeImpl with that ID, or if
	 *         ID is unknown a newly created ReferenceTypeImpl.
	 */
	public static InterfaceTypeImpl read(MirrorImpl target, DataInputStream in)
			throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpInterfaceID ID = new JdwpInterfaceID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("interfaceType", ID.value()); //$NON-NLS-1$
		}

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

		InterfaceTypeImpl mirror = (InterfaceTypeImpl) vmImpl
				.getCachedMirror(ID);
		if (mirror == null) {
			mirror = new InterfaceTypeImpl(vmImpl, ID);
			vmImpl.addCachedMirror(mirror);
		}
		return mirror;
	}

	/**
	 * @return Reads ID and returns known ReferenceTypeImpl with that ID, or if
	 *         ID is unknown a newly created ReferenceTypeImpl.
	 */
	public static InterfaceTypeImpl readWithSignature(MirrorImpl target,
			boolean withGenericSignature, DataInputStream in)
			throws IOException {
		VirtualMachineImpl vmImpl = target.virtualMachineImpl();
		JdwpInterfaceID ID = new JdwpInterfaceID(vmImpl);
		ID.read(in);
		if (target.fVerboseWriter != null) {
			target.fVerboseWriter.println("interfaceType", ID.value()); //$NON-NLS-1$
		}

		String signature = target.readString("signature", in); //$NON-NLS-1$
		String genericSignature = null;
		if (withGenericSignature) {
			genericSignature = target.readString("generic signature", in); //$NON-NLS-1$
		}
		if (ID.isNull()) {
			return null;
		}

		InterfaceTypeImpl mirror = (InterfaceTypeImpl) vmImpl
				.getCachedMirror(ID);
		if (mirror == null) {
			mirror = new InterfaceTypeImpl(vmImpl, ID);
			vmImpl.addCachedMirror(mirror);
		}
		mirror.setSignature(signature);
		mirror.setGenericSignature(genericSignature);
		return mirror;
	}
}
