/*******************************************************************************
 * 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.declaration;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.apt.core.internal.EclipseMirrorImpl;
import org.eclipse.jdt.apt.core.internal.env.ProcessorEnvImpl;
import org.eclipse.jdt.apt.core.internal.util.Factory;
import org.eclipse.jdt.apt.core.internal.util.SourcePositionImpl;
import org.eclipse.jdt.core.dom.*;

import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.type.AnnotationType;
import com.sun.mirror.util.SourcePosition;

/**
 * Annotation instance from source.
 */
public class AnnotationMirrorImpl implements AnnotationMirror, EclipseMirrorImpl
{
    /**The ast node that correspond to the annotation.*/
    private final IResolvedAnnotation _domAnnotation;
    private final ProcessorEnvImpl _env;
    /** the declaration that is annotated by this annotation or the annotation element declaration
     *  if this is (part of) a default value*/
    private final DeclarationImpl _annotated;
    
    public AnnotationMirrorImpl(IResolvedAnnotation annotationAstNode, DeclarationImpl decl, ProcessorEnvImpl env)
    {
		_domAnnotation = annotationAstNode;
        _env = env;
        _annotated = decl;
        assert _domAnnotation != null : "annotation node missing.";
        assert _annotated   != null : "missing the declaration that is annotated with this annotation.";
    }
	
    public AnnotationType getAnnotationType()
    {		
        final ITypeBinding binding = _domAnnotation.getAnnotationType();
		return (AnnotationType)Factory.createReferenceType(binding, _env);        
    }

    public Map<AnnotationTypeElementDeclaration, AnnotationValue> getElementValues()
    {
		final IResolvedMemberValuePair[] pairs = _domAnnotation.getDeclaredMemberValuePairs();
		if (pairs.length == 0) {
			return Collections.emptyMap();
		}
		
		final Map<AnnotationTypeElementDeclaration, AnnotationValue> result =
			new LinkedHashMap<AnnotationTypeElementDeclaration, AnnotationValue>(pairs.length * 4 / 3 + 1 );
		for( IResolvedMemberValuePair pair : pairs ){
			 final String name = pair.getName();
             if( name == null ) continue;
             IMethodBinding elementMethod = pair.getMemberBinding();            
             if( elementMethod != null ){
                 final DeclarationImpl mirrorDecl = Factory.createDeclaration(elementMethod, _env);
                 final AnnotationValue annoValue = 
					 Factory.createAnnotationMemberValue(pair.getValue(), name, this, _env);
                 if( mirrorDecl.kind() == EclipseMirrorImpl.MirrorKind.ANNOTATION_ELEMENT  &&
                     annoValue != null )
                     result.put( (AnnotationTypeElementDeclaration)mirrorDecl, annoValue);
             }
		}
        return result;
    }

    public SourcePosition getPosition()
    {
		if( isFromSource() ){
			final CompilationUnit unit = _annotated.getCompilationUnit();
			final org.eclipse.jdt.core.dom.Annotation annotation = getAstNode();
			if( annotation == null ) return null;
			org.eclipse.jdt.core.dom.ASTNode astNode = annotation.getTypeName();
			if( astNode == null )
				astNode = annotation;
			
			final int offset = astNode.getStartPosition();
			// TODO: waiting on new API Bugzilla #97766
			return new SourcePositionImpl(astNode.getStartPosition(),
										  astNode.getLength(),
						                  unit.lineNumber(offset),
						                  0,//unit.columnNumber(offset), 
						                  _annotated);
		}
		return null;
    }

    public String toString()
    {
		return _domAnnotation.toString();			
    }

    /**
     * @return the type(s) of the member value named <code>membername</code>.
     * If the value is a class literal, then return the type binding corresponding to the type requested.
     * Otherwise, return the type of the expression.
     * If the value is an array initialization, then the type of each of the initialization expresion will
     * be returned. Return null if no match is found.
     */
    public ITypeBinding[] getMemberValueTypeBinding(String membername)
    {
        if( membername == null ) return null;
		final IResolvedMemberValuePair[] declaredPairs = _domAnnotation.getDeclaredMemberValuePairs();
		for( IResolvedMemberValuePair pair : declaredPairs ){			
			if( membername.equals(pair.getName()) ){
				final Object value = pair.getValue();
				return getValueTypeBinding(value, pair.getMemberBinding().getReturnType());
			}
		}
      
        // didn't find it in the ast, check the default values.
        final IMethodBinding binding = getMethodBinding(membername);
		if(binding == null ) return null;
		final Object defaultValue = binding.getDefaultValue();
		if( defaultValue != null )		
			return getValueTypeBinding(defaultValue, binding.getReturnType() );
		else
			return null;		
    }
	
	private ITypeBinding[] getValueTypeBinding(Object value, final ITypeBinding resolvedType)
	{
		if( value == null ) return null;		
		if( resolvedType.isPrimitive() ||  resolvedType.isAnnotation() || value instanceof String )
			return new ITypeBinding[]{ resolvedType };
		else if( resolvedType.isArray() ){
			final Object[] elements = (Object[])value;
			final ITypeBinding[] result = new ITypeBinding[elements.length];
			final ITypeBinding leafType = resolvedType.getElementType();
			for(int i=0, len = elements.length; i<len; i++ ){
				final ITypeBinding[] t = getValueTypeBinding(elements[i], leafType);
				result[i] = t == null ? null : t[0];
			}
			return result;
		}		 
		else if( value instanceof IVariableBinding )
			return new ITypeBinding[]{ ( (IVariableBinding)value ).getDeclaringClass() };
		else if( value instanceof ITypeBinding )
			return new ITypeBinding[]{ (ITypeBinding)value };
		else
			throw new IllegalStateException("value = " + value + " resolvedType = " + resolvedType );
		
	}

    private ITypeBinding[] getExpressionTypeBindings(Expression expr)
    {
        if(expr == null) return null;
        switch(expr.getNodeType())
        {
        case ASTNode.ARRAY_INITIALIZER:
            final ArrayInitializer arrayInit = (ArrayInitializer)expr;
            final List<Expression> exprs = arrayInit.expressions();
            if( exprs == null || exprs.size() == 0 )
                return new ITypeBinding[0];
            final ITypeBinding[] bindings = new ITypeBinding[exprs.size()];
            for( int i=0, size = exprs.size(); i<size; i++ ){
                final Expression initExpr = exprs.get(i);
                bindings[i] = getExpressionTypeBinding(initExpr);
            }
            return bindings;
        default:
            return new ITypeBinding[]{ getExpressionTypeBinding(expr) };
        }
    }

    private ITypeBinding getExpressionTypeBinding(Expression expr)
    {
        if( expr.getNodeType() == ASTNode.TYPE_LITERAL )
            return  ((TypeLiteral)expr).getType().resolveBinding();
        else
            return expr.resolveTypeBinding();
    }

    /**
     * @param memberName the name of the member
     * @return the value of the given member
     */
    private Object getValue(final String memberName)
    {
		if( memberName == null ) return null;
		final IResolvedMemberValuePair[] declaredPairs = _domAnnotation.getDeclaredMemberValuePairs();
		for( IResolvedMemberValuePair pair : declaredPairs ){			
			if( memberName.equals(pair.getName()) ){
				return pair.getValue();				
			}
		}
      
        // didn't find it in the ast, check the default values.
        final IMethodBinding binding = getMethodBinding(memberName);
		if(binding == null ) return null;
		return binding.getDefaultValue();
    }

    /**
     * @return the method binding that matches the given name from the annotation type
     *         referenced by this annotation.
     */
    public IMethodBinding getMethodBinding(final String memberName)
    {
        if( memberName == null ) return null;
        final ITypeBinding typeBinding = _domAnnotation.getAnnotationType();
		if( typeBinding == null ) return null;
        final IMethodBinding[] methods  = typeBinding.getDeclaredMethods();
        for( IMethodBinding method : methods ){
            if( memberName.equals(method.getName()) )
                return method;
        }
        return null;
    }

    public Object getReflectionValue(String memberName, Method method)
        throws Throwable
    {
        if(memberName == null || memberName.length() == 0 ) return null;
        final Class targetType = method.getReturnType();
        final Object value = getValue(memberName);	
        return getReflectionValue(value, targetType);
    }

    private Object getReflectionValue(final Object value, final Class targetType)
        throws Throwable
    {
        if( value == null ) return null;
        else if(value instanceof Boolean   ||
				value instanceof Byte      ||
				value instanceof Character ||
				value instanceof Double    || 
				value instanceof Float     ||
				value instanceof Integer   ||
				value instanceof Long      ||
				value instanceof Short     ||
				value instanceof String ) 
			return value;
        else if( value instanceof IVariableBinding )
		{
			final IVariableBinding varBinding = (IVariableBinding)value;
            final ITypeBinding declaringClass = varBinding.getDeclaringClass();
            if( declaringClass != null ){
                final String className = new String( declaringClass.getBinaryName() );
                final Class clazz = value.getClass().getClassLoader().loadClass( className );
                final Field returnedField = clazz.getField( varBinding.getName() );
                if( returnedField.getType() != targetType )
                    throw new ClassCastException( targetType.getName() );
                return returnedField.get(null);
            }
		}
        else if (value instanceof Object[])
		{
			final Object[] elements = (Object[])value;
			assert targetType.isArray();
            final Class componentType = targetType.getComponentType();
            final char componentTypeName = componentType.getName().charAt(0);
            final int length = elements.length;;
            final Object array = Array.newInstance(componentType, length);
            if( length == 0) return array;

            for( int i=0; i<length; i++ ){                
                final Object returnObj = getReflectionValue( elements[i], componentType );
                // fill in the array.
                // If it is an array of some primitive type, we will need to unwrap it.
                if( componentType.isPrimitive() ){
                    if( componentType == boolean.class ){
                        final Boolean bool = (Boolean)returnObj;
                        Array.setBoolean( array, i, bool.booleanValue());
                    }
                    else if( componentType == byte.class ){
                        final Byte b = (Byte)returnObj;
                        Array.setByte( array, i, b.byteValue() );
                    }
                    else if( componentType == char.class ){
                        final Character c = (Character)returnObj;
                        Array.setChar( array, i, c.charValue() );
                    }
                    else if( componentType == double.class ){
                        final Double d = (Double)returnObj;
                        Array.setDouble( array, i, d.doubleValue() );
                    }
                    else if( componentType == float.class ){
                        final Float f = (Float)returnObj;
                        Array.setFloat( array, i, f.floatValue() );
                    }
                    else if( componentType == int.class ){
                        final Integer integer = (Integer)returnObj;
                        Array.setInt( array, i, integer.intValue() );
                    }
                    else if( componentType == long.class ){
                        final Long l = (Long)returnObj;
                        Array.setLong( array, i, l.longValue() );
                    }
                    else if( componentType == short.class ){
                        final Short s = (Short)returnObj;
                        Array.setShort( array, i, s.shortValue() );
                    }
                    else {
                        throw new IllegalStateException("unrecognized primitive type: "  + componentType );
                    }
                }
                else{
                    Array.set( array, i, returnObj );
                }
            }
		}
		// caller should have caught this case.
        else if( value instanceof ITypeBinding )
			throw new IllegalStateException();
		
        else if( value instanceof IResolvedAnnotation )
		{
			return Factory.createAnnotationMirror((IResolvedAnnotation)value, _annotated, _env);
		}

        return null;
    }

    public MirrorKind kind(){ return MirrorKind.ANNOTATION_MIRROR; }

    boolean isFromSource()
	{  
		return _annotated.isFromSource();		
	}

    org.eclipse.jdt.core.dom.Annotation getAstNode()
	{ 
		if( isFromSource() ){
			final CompilationUnit unit = _annotated.getCompilationUnit();
			final ASTNode node = unit.findDeclaringNode(_domAnnotation);
			if( node instanceof org.eclipse.jdt.core.dom.Annotation )
				return (org.eclipse.jdt.core.dom.Annotation)node;			
		}	
		return null;
    }
	
	ASTNode getASTNodeForElement(String name)
	{
		if( name == null ) return null;
		final org.eclipse.jdt.core.dom.Annotation anno = getAstNode();
		if( anno != null ){
			if( anno.isSingleMemberAnnotation() ){
				if( "value".equals(name) )
					return ((SingleMemberAnnotation)anno).getValue();
			}
			else if( anno.isNormalAnnotation() ){
				final List<MemberValuePair> pairs = ((NormalAnnotation)anno).values();
				for( MemberValuePair pair : pairs )
				{
					final String pairName = pair.getName() == null ? null : pair.getName().toString();
					if( name.equals(pairName) )
						return pair.getValue();
				}
			}
		}
		// marker annotation or no match.
		return null;
	}

    CompilationUnit getCompilationUnit() { return _annotated.getCompilationUnit(); }

	public ProcessorEnvImpl getEnvironment(){ return _env; }
	
	public IFile getResouce()
	{ 	return _annotated.getResource(); }
	
	public DeclarationImpl getAnnotatedDeclaration(){ return _annotated; }

    public boolean equals(Object obj){
        if( obj instanceof AnnotationMirrorImpl ){
            return ((AnnotationMirrorImpl)obj)._domAnnotation == _domAnnotation;
        }
        return false;
    }

    public int hashCode(){
        return _domAnnotation.hashCode();
    }
}
