/*******************************************************************************
 * Copyright (c) 2005 BEA Systems, Inc.
 * 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:
 *    tyeung@bea.com - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.apt.core.internal.util;

import com.sun.mirror.declaration.PackageDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.declaration.TypeParameterDeclaration;
import com.sun.mirror.type.ArrayType;
import com.sun.mirror.type.DeclaredType;
import com.sun.mirror.type.PrimitiveType;
import com.sun.mirror.type.ReferenceType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.type.TypeVariable;
import com.sun.mirror.type.VoidType;
import com.sun.mirror.type.WildcardType;
import com.sun.mirror.util.Types;
import java.util.Collection;
import org.eclipse.jdt.apt.core.internal.EclipseMirrorImpl;
import org.eclipse.jdt.apt.core.internal.NonEclipseImplementationException;
import org.eclipse.jdt.apt.core.internal.declaration.PackageDeclarationImpl;
import org.eclipse.jdt.apt.core.internal.declaration.TypeDeclarationImpl;
import org.eclipse.jdt.apt.core.internal.declaration.TypeParameterDeclarationImpl;
import org.eclipse.jdt.apt.core.internal.env.BaseProcessorEnv;
import org.eclipse.jdt.apt.core.internal.type.ArrayTypeImpl;
import org.eclipse.jdt.apt.core.internal.type.PrimitiveTypeImpl;
import org.eclipse.jdt.apt.core.internal.type.VoidTypeImpl;
import org.eclipse.jdt.apt.core.internal.type.WildcardTypeImpl;
import org.eclipse.jdt.core.BindingKey;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;

public class TypesUtil implements Types
{	
	private static final String[] NO_ARGS = new String[0];
    private final BaseProcessorEnv _env;
	
	public static void main(String[] args){}

    public TypesUtil(BaseProcessorEnv env){
        _env = env;
        assert env != null : "null environment."; //$NON-NLS-1$
    }
    
    public ArrayType getArrayType(TypeMirror componentType)
    {
        if( componentType == null ) return null;
        if( componentType instanceof EclipseMirrorImpl ){
            final EclipseMirrorImpl impl = (EclipseMirrorImpl)componentType;
            // the leaf type of the array
            final ITypeBinding leaf;
            final int dimension;
            switch( impl.kind() )
            {
                case TYPE_ERROR:
                    throw new IllegalArgumentException("cannot create an array from error type"); //$NON-NLS-1$
                case TYPE_VOID:
                    throw new IllegalArgumentException("cannot create an array from void type"); //$NON-NLS-1$
                case TYPE_PRIMITIVE:
                    leaf = ((PrimitiveTypeImpl)componentType).getTypeBinding();
                    dimension = 1;
                    break;
                case TYPE_ARRAY:
                    final ITypeBinding array = ((ArrayTypeImpl)componentType).getArrayBinding();
                    dimension = array.getDimensions() + 1;
                    leaf = array.getElementType();
                    break;
                case TYPE_WILDCARD:
                    leaf = ((WildcardTypeImpl)componentType).getWildcardBinding();
                    dimension = 1;
                    break;
                default:
                    leaf = ((TypeDeclarationImpl)componentType).getTypeBinding();
                    dimension = 1;
            }
            if( leaf == null || leaf.isParameterizedType() )
                throw new IllegalArgumentException("illegal component type: " + componentType); //$NON-NLS-1$

            final String bindingKey = BindingKey.createArrayTypeBindingKey(leaf.getKey(), dimension);
			final ITypeBinding arrayType = _env.getTypeBinding(bindingKey);
			if(arrayType == null)
				return null;
			return (ArrayType)Factory.createTypeMirror(arrayType, _env); 
        }
		
        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + componentType.getClass().getName()); //$NON-NLS-1$
                                                
    }

    /**
     * @param outer a type
     * @param inner the simple name of the nested class
     * @return the binding that correspond to <code>outer.getQualifiedName()</code>.<code>inner</code>
     * 		   or null if it cannot be located.
     */
    private ITypeBinding findMemberType(ITypeBinding outer, String inner )
    {
        if( outer == null || inner == null ) return null;        

        outer = outer.getTypeDeclaration();        

        final ITypeBinding[] nestedTypes = outer.getDeclaredTypes();
        // first we search throw the ones that are directly declared within 'outer'
        for( ITypeBinding nestedType : nestedTypes ){
            if( inner.equals(nestedType.getName()) )
                return nestedType;
        }
		// then we look up the hierachy chain.
		// first we search the super type
		ITypeBinding result = findMemberType(outer.getSuperclass(), inner);
		if( result != null ) return result;
		
		// then the super interfaces
		final ITypeBinding[] interfaces = outer.getInterfaces();
		for( ITypeBinding interfaceType : interfaces ){
			result = findMemberType(interfaceType, inner);
			if( result != null ) return result;
		}
        
		// can't find it.
		return null;
    }

    public com.sun.mirror.type.DeclaredType getDeclaredType(DeclaredType containing, TypeDeclaration decl, TypeMirror... typeArgs)
    {
		if( decl == null ) return null;
	
        final ITypeBinding outerBinding = getTypeBinding(containing);
		final ITypeBinding memberBinding;
		
		if( containing == null )
			memberBinding = getTypeBinding(decl);
		else{
			if( outerBinding.isGenericType() )
	             throw new IllegalArgumentException("[containing], " + containing + ", is a generic type."); //$NON-NLS-1$ //$NON-NLS-2$
			 // make sure 'decl' is a valid member of 'outerBinding'
			memberBinding = findMemberType(outerBinding, decl.getSimpleName() );
			if( memberBinding == null )        
	            throw new IllegalArgumentException(decl + " is not a member type of " + containing ); //$NON-NLS-1$
		}
		
		final int numArgs = typeArgs == null ? 0 : typeArgs.length;		
		
		if( memberBinding.isGenericType() ){
			final String[] argKeys = numArgs == 0 ? NO_ARGS : new String[numArgs];
			for( int i=0; i<numArgs; i++ ){		
				final ITypeBinding binding = getTypeBinding(typeArgs[i]);
				assert binding != null : "failed to get binding mirror type"; //$NON-NLS-1$
				argKeys[i] = binding.getKey();
			}
			
			final ITypeBinding[] typeParams = memberBinding.getTypeParameters();
			final int numTypeParams = typeParams == null ? 0 : typeParams.length;
			// if no argument then a raw type will be created, otherwise it's an error when the 
			// number of type parameter and arguments don't agree.
			if( numTypeParams != numArgs && numArgs != 0 )
				throw new IllegalArgumentException("type, " + memberBinding.getQualifiedName() + ", require " + numTypeParams + " type arguments " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        "but found " + numArgs ); //$NON-NLS-1$
			
			final String typeKey = BindingKey.createParameterizedTypeBindingKey(memberBinding.getKey(), argKeys);
			final ITypeBinding resultBinding = _env.getTypeBinding(typeKey);
			return Factory.createReferenceType(resultBinding, _env);
		}
		else{ 
			if( numArgs != 0 )
				throw new IllegalArgumentException("type, " + memberBinding + " is not a generic type and cannot have type arguments."); //$NON-NLS-1$ //$NON-NLS-2$
			// simple case, turning a non-generic TypeDeclaration into a DeclaredType
			return (DeclaredType)decl;
		}	
    }

    public com.sun.mirror.type.DeclaredType getDeclaredType(TypeDeclaration decl, TypeMirror... typeArgs)
    {
		return getDeclaredType(null, decl, typeArgs);		
    }

    public TypeMirror getErasure(TypeMirror t)
    {	
        if( t == null ) return null;
        
        if(t instanceof EclipseMirrorImpl){
            final EclipseMirrorImpl impl = (EclipseMirrorImpl)t;
            final ITypeBinding binding;
            switch( impl.kind() )
            {
                case TYPE_PRIMITIVE:
                case TYPE_VOID:
                case TYPE_ERROR:
                    return t;
                case TYPE_ARRAY:
                    binding = ((ArrayTypeImpl)t).getArrayBinding();
                    break;
                case TYPE_WILDCARD:
                    binding = ((WildcardTypeImpl)t).getWildcardBinding();                   
                    break;
                default:
                    binding = ((TypeDeclarationImpl)t).getTypeBinding();
            }
            final ITypeBinding erasure = binding.getErasure();
            if( erasure == binding ) return t;
            TypeMirror m_erasure = Factory.createTypeMirror(erasure, impl.getEnvironment() );
            if( m_erasure == null )
                return Factory.createErrorClassType(erasure);
            return m_erasure;
        }

        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + t.getClass().getName());	 //$NON-NLS-1$
	}

    public PrimitiveType getPrimitiveType(PrimitiveType.Kind kind)
    {
        if( kind == null ) return null;
        switch(kind)
        {
            case BOOLEAN: return _env.getBooleanType();
            case BYTE:    return _env.getByteType();
            case CHAR:    return _env.getCharType();
            case DOUBLE:  return _env.getDoubleType();
            case FLOAT:   return _env.getFloatType();
            case INT:     return _env.getIntType();
            case LONG:    return _env.getLongType();
            case SHORT:   return _env.getShortType();
          
            default: throw new IllegalStateException("unknown primitive kind : " + kind); //$NON-NLS-1$
        }
    }

    public TypeVariable getTypeVariable(TypeParameterDeclaration tparam)
    {
        if( tparam == null ) return null;
        if( tparam instanceof TypeParameterDeclarationImpl)
            return (TypeVariable) tparam;

        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + tparam.getClass().getName()); //$NON-NLS-1$
    }

    public VoidType getVoidType()
    {
        return _env.getVoidType();
    }

    public WildcardType getWildcardType(Collection<ReferenceType> upperBounds, Collection<ReferenceType> lowerBounds)
    {		
        final String boundKey;
        final char boundKind;
        final int upperBoundCount = upperBounds == null ? 0 : upperBounds.size();
        final int lowerBoundCount = lowerBounds == null ? 0 : lowerBounds.size();
        if( upperBoundCount == 0  && lowerBoundCount == 0 ){
			boundKey = null;
            boundKind = Signature.C_STAR;
        }
        else if( upperBoundCount == 1 && lowerBoundCount == 0){
			final ITypeBinding binding = getTypeBinding(upperBounds.iterator().next());
			boundKey = binding.getKey();
            boundKind = Signature.C_EXTENDS;
        }
        else if(lowerBoundCount == 1 && upperBoundCount == 0){
			final ITypeBinding binding = getTypeBinding(lowerBounds.iterator().next());
			boundKey = binding.getKey();
            boundKind = Signature.C_SUPER;
        }
        else
            throw new IllegalArgumentException("Wildcard can only have a upper bound, a lower bound or be unbounded."); //$NON-NLS-1$

		final String wildcardkey = BindingKey.createWilcardTypeBindingKey(boundKey, boundKind);
		final ITypeBinding wildcard = _env.getTypeBinding(wildcardkey);
        return (WildcardType)Factory.createTypeMirror(wildcard, _env);
    }

    /**
     * @return true iff t2 = t1 does not require explicit casting and not cause an error.
     */
    public boolean isAssignable(TypeMirror t1, TypeMirror t2)
    {
        final ITypeBinding left = getTypeBinding(t2);
        final ITypeBinding right = getTypeBinding(t1);
        
        if( left == right ) return true;
        else if( left == null || right == null ) return false;
        return right.isAssignmentCompatible(left);       
    }

    public boolean isSubtype(TypeMirror t1, TypeMirror t2)
    {
        final ITypeBinding b1 = getTypeBinding(t1);
        final ITypeBinding b2 = getTypeBinding(t2);
        if( b1 == null || b2 == null ) return false;

        return b1.isSubTypeCompatible(b2);
    }
    
    public static IPackageBinding getPackageBinding(PackageDeclaration pkg)
    	throws NonEclipseImplementationException
    {	
        if(pkg == null) return null;
        if( pkg instanceof EclipseMirrorImpl ){
            final PackageDeclarationImpl impl = (PackageDeclarationImpl)pkg;
            return impl.getPackageBinding();
        }

        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + pkg.getClass().getName()); //$NON-NLS-1$
    }  

    /**
     * @return the binding correspond to the given type.
     *         Return null if the type is an error marker.
     * @throws NonEclipseImplementationException
     */

    public static ITypeBinding getTypeBinding(TypeMirror type)
        throws NonEclipseImplementationException
    {	
        if(type == null ) return null;
        if( type instanceof EclipseMirrorImpl ){
            final EclipseMirrorImpl impl = (EclipseMirrorImpl)type;
            switch(impl.kind() )
            {
                case TYPE_PRIMITIVE: return ((PrimitiveTypeImpl)type).getTypeBinding();
                case TYPE_VOID:  	 return ((VoidTypeImpl)type).getTypeBinding();
                case TYPE_ERROR: 	 return null;
                case TYPE_ARRAY: 	 return ((ArrayTypeImpl)type).getArrayBinding();
                case TYPE_WILDCARD:  return ((WildcardTypeImpl)type).getWildcardBinding();
                case TYPE_PARAMETER_VARIABLE: return ((TypeParameterDeclarationImpl)type).getDeclarationBinding();
                default: return ((TypeDeclarationImpl)type).getTypeBinding();
            }
        }

        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + type.getClass().getName()); //$NON-NLS-1$
    }

    /**
     * @return the binding correspond to the given type.
     * @throws NonEclipseImplementationException
     */
    public static ITypeBinding getTypeBinding(TypeDeclaration type)
        throws NonEclipseImplementationException
    {
        if(type == null ) return null;
        if( type instanceof EclipseMirrorImpl ){           
            return ((TypeDeclarationImpl)type).getTypeBinding();
        }
        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + type.getClass().getName()); //$NON-NLS-1$
    } 
}
