/*******************************************************************************
 * Copyright (c) 2004 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:
 *     Luzius Meisser - initial implementation
 *******************************************************************************/
package org.eclipse.ajdt.core.javaelements;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.aspectj.asm.IHierarchy;
import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.IProgramElement.Accessibility;
import org.aspectj.asm.IProgramElement.ExtraInformation;
import org.aspectj.asm.IProgramElement.Kind;
import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.eclipse.ajdt.core.model.AJProjectModelFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;

/**
 * @author Luzius Meisser
 */
public class AspectElement extends SourceType implements IAspectJElement {
	
	// characters to use for handle identifiers, alongside the ones in JavaElement
	public static final char JEM_ASPECT_CU = '*';
	public static final char JEM_ADVICE = '&';
	public static final char JEM_ASPECT_TYPE = '}';
	public static final char JEM_CODEELEMENT = '?';
	public static final char JEM_ITD = ')';
	public static final char JEM_DECLARE = '`';
	public static final char JEM_POINTCUT = '+';
	// TYPE_PARAMETER is defined in Eclipse 3.1, but not 3.0
	public static final char JEM_TYPE_PARAMETER = ']';
//	public static final char JEM_EXTRA_INFO = '>';
	
	public IMethod createMethod(String contents, IJavaElement sibling,
			boolean force, IProgressMonitor monitor) throws JavaModelException {
		IMethod result = super.createMethod(contents, sibling, force, monitor);
		return result;
	}
	public AspectElement(JavaElement parent, String name) {
		super(parent, name);
	}

	public int getType() {
		return TYPE;
	}
	
    protected Object createElementInfo() {
        AspectElementInfo info = new AspectElementInfo();
        info.setAJKind(IProgramElement.Kind.ASPECT);
        info.setHandle(this);
        info.setSourceRangeStart(0);
        
        IProgramElement ipe = AJProjectModelFactory.getInstance().getModelForJavaElement(this).javaElementToProgramElement(this);
        if (ipe != IHierarchy.NO_STRUCTURE) {
            info.setAJExtraInfo(ipe.getExtraInfo());
            info.setAJModifiers(ipe.getModifiers());
            info.setFlags(getProgramElementModifiers(ipe));
            info.setAJAccessibility(ipe.getAccessibility());
            ISourceLocation sourceLocation = ipe.getSourceLocation();
            info.setSourceRangeStart(sourceLocation.getOffset());
            info.setNameSourceStart(sourceLocation.getOffset());
            info.setNameSourceEnd(sourceLocation.getOffset() + ipe.getName().length());
        }
        
        
        return info;
    }

	/**
	 * Returns the pointcuts declared by this type. If this is a source type,
	 * the results are listed in the order in which they appear in the source,
	 * otherwise, the results are in no particular order.
	 * 
	 * @exception JavaModelException
	 *                if this element does not exist or if an exception occurs
	 *                while accessing its corresponding resource.
	 * @return the pointcuts declared by this type
	 */
	public PointcutElement[] getPointcuts() throws JavaModelException {
		// pointcuts appear as methods
		IMethod[] methods = getMethods();
		List list = new ArrayList();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i] instanceof PointcutElement) {
				list.add(methods[i]);
			}
		}
		PointcutElement[] array= new PointcutElement[list.size()];
		list.toArray(array);
		return array;
	}

	/**
	 * Returns the advice elements declared by this type. If this is a source
	 * type, the results are listed in the order in which they appear in the
	 * source, otherwise, the results are in no particular order.
	 * 
	 * @exception JavaModelException
	 *                if this element does not exist or if an exception occurs
	 *                while accessing its corresponding resource.
	 * @return the advice elements declared by this type
	 */
	public AdviceElement[] getAdvice() throws JavaModelException {
		// advice statements appear as methods
		IMethod[] methods = getMethods();
		List list = new ArrayList();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i] instanceof AdviceElement) {
				list.add(methods[i]);
			}
		}
		AdviceElement[] array = new AdviceElement[list.size()];
		list.toArray(array);
		return array;
	}

	/**
	 * Returns the declare elements declared by this type. If this is a source
	 * type, the results are listed in the order in which they appear in the
	 * source, otherwise, the results are in no particular order.
	 * 
	 * @exception JavaModelException
	 *                if this element does not exist or if an exception occurs
	 *                while accessing its corresponding resource.
	 * @return the declare elements declared by this type
	 */
	public DeclareElement[] getDeclares() throws JavaModelException {
		// declare statements appear as methods
		IMethod[] methods = getMethods();
		List list = new ArrayList();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i] instanceof DeclareElement) {
				list.add(methods[i]);
			}
		}
		DeclareElement[] array = new DeclareElement[list.size()];
		list.toArray(array);
		return array;
	}

	/**
	 * Returns the declare elements declared by this type. If this is a source
	 * type, the results are listed in the order in which they appear in the
	 * source, otherwise, the results are in no particular order.
	 * 
	 * @exception JavaModelException
	 *                if this element does not exist or if an exception occurs
	 *                while accessing its corresponding resource.
	 * @return the declare elements declared by this type
	 */
	public IntertypeElement[] getITDs() throws JavaModelException {
		// ITDs statements appear as methods
		IMethod[] methods = getMethods();
		List list = new ArrayList();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i] instanceof IntertypeElement) {
				list.add(methods[i]);
			}
		}
		IntertypeElement[] array = new IntertypeElement[list.size()];
		list.toArray(array);
		return array;
	}

	//TODO: forward call to ElementInfo (only for cosmetical reasons)
	public Kind getAJKind() throws JavaModelException  {
		IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo();
		return info.getAJKind();
	}

	public Accessibility getAJAccessibility() throws JavaModelException {
		IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo();
		return info.getAJAccessibility();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ajdt.javamodel.javaelements.IAspectJElement#getAJModifiers()
	 */
	public List getAJModifiers() throws JavaModelException {
		IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo();
		return info.getAJModifiers();
	}
	/* (non-Javadoc)
	 * @see org.eclipse.ajdt.javamodel.javaelements.IAspectJElement#getAJExtraInformation()
	 */
	public ExtraInformation getAJExtraInformation() throws JavaModelException {
		IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo();
		return info.getAJExtraInfo();
	}
	
	/**
	 * @see JavaElement#getHandleMemento()
	 */
	protected char getHandleMementoDelimiter() {
		return AspectElement.JEM_ASPECT_TYPE;
	}
	
	/*
	 * Derived from JEM_METHOD clause in SourceType
	 * Added support for advice, ITDs, and declare statements
	 * @see JavaElement
	 */
	public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
		if (token.charAt(0) == AspectElement.JEM_ADVICE) {
		    token = null;
			if (!memento.hasMoreTokens()) return this;
			String name = memento.nextToken();
			
			ArrayList params = new ArrayList();
			nextParam: while (memento.hasMoreTokens()) {
				token = memento.nextToken();
				switch (token.charAt(0)) {
					case JEM_TYPE:
                        break nextParam;
					case JEM_TYPE_PARAMETER:
					    token = null;
						break nextParam;
					case JEM_ADVICE:
						if (!memento.hasMoreTokens()) return this;
						String param = memento.nextToken();
						StringBuffer buffer = new StringBuffer();
						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
							buffer.append(Signature.C_ARRAY);
							if (!memento.hasMoreTokens()) return this;
							param = memento.nextToken();
						}
						params.add(buffer.toString() + param);
						token = null;
						break;
					default:
						break nextParam;
				}
			}
			String[] parameters = new String[params.size()];
			params.toArray(parameters);
			
			JavaElement advice = new AdviceElement(this, name, parameters);
			if (token != null) {
			    return advice.getHandleFromMemento(token, memento, workingCopyOwner);
			} else {
			    return advice;
			}
		} else if (token.charAt(0) == AspectElement.JEM_ITD) {
			String name = memento.nextToken();
			ArrayList params = new ArrayList();
			nextParam: while (memento.hasMoreTokens()) {
				token = memento.nextToken();
				switch (token.charAt(0)) {
					case JEM_TYPE:
					case JEM_TYPE_PARAMETER:
						break nextParam;
					case JEM_ITD:
						if (!memento.hasMoreTokens()) return this;
						String param = memento.nextToken();
						StringBuffer buffer = new StringBuffer();
						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
							buffer.append(Signature.C_ARRAY);
							if (!memento.hasMoreTokens()) return this;
							param = memento.nextToken();
						}
						params.add(buffer.toString() + param);
						break;
					default:
						break nextParam;
				}
			}
			String[] parameters = new String[params.size()];
			params.toArray(parameters);
			JavaElement itd = new IntertypeElement(this, name, parameters);
			if (memento.hasMoreTokens()) {
			    return itd.getHandleFromMemento(token, memento, workingCopyOwner);
			} else {
			    return itd;
			}
		} else if (token.charAt(0) == AspectElement.JEM_DECLARE) {
			String name = memento.nextToken();
			ArrayList params = new ArrayList();
			nextParam: while (memento.hasMoreTokens()) {
				token = memento.nextToken();
				switch (token.charAt(0)) {
					case JEM_TYPE:
					case JEM_TYPE_PARAMETER:
						break nextParam;
					case JEM_DECLARE:
						if (!memento.hasMoreTokens()) return this;
						String param = memento.nextToken();
						StringBuffer buffer = new StringBuffer();
						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
							buffer.append(Signature.C_ARRAY);
							if (!memento.hasMoreTokens()) return this;
							param = memento.nextToken();
						}
						params.add(buffer.toString() + param);
						break;
					default:
						break nextParam;
				}
			}
			String[] parameters = new String[params.size()];
			params.toArray(parameters);
			JavaElement itd = new DeclareElement(this, name, parameters);
			if (token.charAt(0) == JavaElement.JEM_COUNT) {
				return itd.getHandleFromMemento(token, memento, workingCopyOwner);
			}
			return itd.getHandleFromMemento(memento, workingCopyOwner);
		} else if (token.charAt(0) == AspectElement.JEM_POINTCUT) {
			String name = memento.nextToken();
			ArrayList params = new ArrayList();
			nextParam: while (memento.hasMoreTokens()) {
				token = memento.nextToken();
				switch (token.charAt(0)) {
					case JEM_TYPE:
					case JEM_TYPE_PARAMETER:
						break nextParam;
					case JEM_POINTCUT:
						if (!memento.hasMoreTokens()) return this;
						String param = memento.nextToken();
						StringBuffer buffer = new StringBuffer();
						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
							buffer.append(Signature.C_ARRAY);
							if (!memento.hasMoreTokens()) return this;
							param = memento.nextToken();
						}
						params.add(buffer.toString() + param);
						break;
					default:
						break nextParam;
				}
			}
			String[] parameters = new String[params.size()];
			params.toArray(parameters);
			JavaElement pointcut = new PointcutElement(this, name, parameters);
			return pointcut.getHandleFromMemento(memento, workingCopyOwner);
		} else if (token.charAt(0) == AspectElement.JEM_METHOD &&
		       ! (this.getOpenable() instanceof AJCompilationUnit)) {
		    // method must be mocked up if we are an aspect in a 
		    // .class or .java file
		    // cannot get the JavaElementInfo otherwise
            String name = memento.nextToken();
            ArrayList params = new ArrayList();
            nextParam: while (memento.hasMoreTokens()) {
                token = memento.nextToken();
                switch (token.charAt(0)) {
                    case JEM_TYPE:
                    case JEM_TYPE_PARAMETER:
                    case JEM_ANNOTATION:
                        break nextParam;
                    case JEM_METHOD:
                        if (!memento.hasMoreTokens()) return this;
                        String param = memento.nextToken();
                        StringBuffer buffer = new StringBuffer();
                        while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
                            buffer.append(Signature.C_ARRAY);
                            if (!memento.hasMoreTokens()) return this;
                            param = memento.nextToken();
                        }
                        params.add(buffer.toString() + param);
                        break;
                    default:
                        break nextParam;
                }
            }
            String[] parameters = new String[params.size()];
            params.toArray(parameters);
            MockSourceMethod mockMethod = new MockSourceMethod(this, name, parameters);
            switch (token.charAt(0)) {
                case JEM_TYPE:
                case JEM_TYPE_PARAMETER:
                case JEM_LOCALVARIABLE:
                case JEM_ANNOTATION:
                    return mockMethod.getHandleFromMemento(token, memento, workingCopyOwner);
                default:
                    return mockMethod;
            }
		}
		return super.getHandleFromMemento(token, memento, workingCopyOwner);
	}
	
	   static Field modfiersField = null;
	    static int getProgramElementModifiers(IProgramElement ipe) {
	        try {
	            if (modfiersField == null) {
	                modfiersField = ProgramElement.class.getDeclaredField("modifiers");
	                modfiersField.setAccessible(true);
	            }
	            return modfiersField.getInt(ipe);
	        } catch (SecurityException e) {
	        } catch (IllegalArgumentException e) {
	        } catch (NoSuchFieldException e) {
	        } catch (IllegalAccessException e) {
	        }
	        return -1;
	    }

}
