/*******************************************************************************
 * Copyright (c) 2009, 2012 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.core.internal.resource.java.binary;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.common.core.JptCommonCorePlugin;
import org.eclipse.jpt.common.core.resource.java.Annotation;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMember;
import org.eclipse.jpt.common.core.resource.java.JavaResourceNode;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;

/**
 * binary persistent member
 */
abstract class BinaryMember
	extends BinaryAnnotatedElement
	implements JavaResourceMember
{

	private boolean final_;  // 'final' is a reserved word
	private boolean transient_;  // 'transient' is a reserved word
	private boolean public_;  // 'public' is a reserved word
	private boolean static_;  // 'static' is a reserved word
	private boolean protected_; // 'protected' is a reserved word


	// ********** construction/initialization **********

	public BinaryMember(JavaResourceNode parent, Adapter adapter) {
		super(parent, adapter);
		this.final_ = this.buildFinal();
		this.transient_ = this.buildTransient();
		this.public_ = this.buildPublic();
		this.static_ = this.buildStatic();
		this.protected_ = this.buildProtected();
	}


	// ********** updating **********

	@Override
	public void update() {
		super.update();
		this.setFinal(this.buildFinal());
		this.setTransient(this.buildTransient());
		this.setPublic(this.buildPublic());
		this.setStatic(this.buildStatic());
		this.setProtected(this.buildProtected());
	}


	// ********** simple state **********

	// ***** final
	public boolean isFinal() {
		return this.final_;
	}

	private void setFinal(boolean final_) {
		boolean old = this.final_;
		this.final_ = final_;
		this.firePropertyChanged(FINAL_PROPERTY, old, final_);
	}

	private boolean buildFinal() {
		try {
			return Flags.isFinal(this.getMember().getFlags());
		} catch (JavaModelException ex) {
			JptCommonCorePlugin.log(ex);
			return false;
		}
	}

	// ***** transient
	public boolean isTransient() {
		return this.transient_;
	}

	private void setTransient(boolean transient_) {
		boolean old = this.transient_;
		this.transient_ = transient_;
		this.firePropertyChanged(TRANSIENT_PROPERTY, old, transient_);
	}

	private boolean buildTransient() {
		try {
			return Flags.isTransient(this.getMember().getFlags());
		} catch (JavaModelException ex) {
			JptCommonCorePlugin.log(ex);
			return false;
		}
	}

	// ***** public
	public boolean isPublic() {
		return this.public_;
	}

	private void setPublic(boolean public_) {
		boolean old = this.public_;
		this.public_ = public_;
		this.firePropertyChanged(PUBLIC_PROPERTY, old, public_);
	}

	private boolean buildPublic() {
		try {
			return Flags.isPublic(this.getMember().getFlags());
		} catch (JavaModelException ex) {
			JptCommonCorePlugin.log(ex);
			return false;
		}
	}

	// ***** static
	public boolean isStatic() {
		return this.static_;
	}

	private void setStatic(boolean static_) {
		boolean old = this.static_;
		this.static_ = static_;
		this.firePropertyChanged(STATIC_PROPERTY, old, static_);
	}

	private boolean buildStatic() {
		try {
			return Flags.isStatic(this.getMember().getFlags());
		} catch (JavaModelException ex) {
			JptCommonCorePlugin.log(ex);
			return false;
		}
	}

	// ***** protected
	public boolean isProtected() {
		return this.protected_;
	}

	private void setProtected(boolean protected_) {
		boolean old = this.protected_;
		this.protected_ = protected_;
		this.firePropertyChanged(PROTECTED_PROPERTY, old, protected_);
	}

	private boolean buildProtected() {
		try {
			return Flags.isProtected(this.getMember().getFlags());
		} catch (JavaModelException ex) {
			JptCommonCorePlugin.log(ex);
			return false;
		}
	}

	// ********** miscellaneous **********

	IMember getMember() {
		return this.getAdapter().getElement();
	}

	private Adapter getAdapter() {
		return (Adapter) this.adapter;
	}

	/**
	 * Strip off the type signature's parameters if present.
	 * Convert to a readable string.
	 */
	static String convertTypeSignatureToTypeName(String typeSignature) {
		return convertTypeSignatureToTypeName(typeSignature, EmptyIterable.<ITypeParameter>instance());
	}
	
	/**
	 * Strip off the type signature's parameters if present.
	 * Convert to a readable string.
	 */
	static String convertTypeSignatureToTypeName(String typeSignature, Iterable<ITypeParameter> typeParameters) {
		return (typeSignature == null) ? null : convertTypeSignatureToTypeName_(typeSignature, typeParameters);
	}
	
	/**
	 * no null check
	 */
	static String convertTypeSignatureToTypeName_(String typeSignature) {
		return convertTypeSignatureToTypeName(typeSignature, EmptyIterable.<ITypeParameter>instance());
	}
	
	/**
	 * no null check
	 */
	static String convertTypeSignatureToTypeName_(String typeSignature, Iterable<ITypeParameter> typeParameters) {
		String erasureSignature = Signature.getTypeErasure(typeSignature);
		if (Signature.getTypeSignatureKind(erasureSignature) == Signature.TYPE_VARIABLE_SIGNATURE) {
			try {
				String typeParameterName = Signature.toString(erasureSignature);
				for (ITypeParameter typeParameter : typeParameters) {
					if (typeParameterName.equals(typeParameter.getElementName())) {
						String[] bounds = typeParameter.getBoundsSignatures();
						if (bounds.length > 0) {
							return convertTypeSignatureToTypeName_(bounds[0], typeParameters);
						}
					}
				}
			}
			catch (JavaModelException jme) {
				JptCommonCorePlugin.log(jme);
			}
		}
		else if (Signature.getTypeSignatureKind(erasureSignature) == Signature.ARRAY_TYPE_SIGNATURE) {
			int dim = Signature.getArrayCount(erasureSignature);
			String arrayTypeName = convertTypeSignatureToTypeName(Signature.getElementType(erasureSignature), typeParameters);
			return Signature.toString(Signature.createArraySignature(Signature.createTypeSignature(arrayTypeName, true), dim));
		}
		else if (Signature.getTypeSignatureKind(erasureSignature) == Signature.WILDCARD_TYPE_SIGNATURE) {
			// if signature is ? (wildcard) or ? super X (bottom bounded), return top bound, which is Object
			if (String.valueOf(Signature.C_STAR).equals(erasureSignature) || erasureSignature.startsWith(String.valueOf(Signature.C_SUPER))) {
				return Object.class.getName();
			}
			// return top bound
			return Signature.toString(erasureSignature.substring(1));
		}
		return Signature.toString(erasureSignature);
	}
	
	static boolean convertTypeSignatureToTypeIsArray(String typeSignature) {
		return (typeSignature == null) ? false : Signature.getTypeSignatureKind(typeSignature) == Signature.ARRAY_TYPE_SIGNATURE;
	}
	
	static int convertTypeSignatureToTypeArrayDimensionality(String typeSignature) {
		return (typeSignature == null) ? 0 : Signature.getArrayCount(typeSignature);
	}
	
	static String convertTypeSignatureToTypeArrayComponentTypeName(String typeSignature, Iterable<ITypeParameter> typeParameters) {
		return (typeSignature == null) ? null : convertTypeSignatureToTypeName(Signature.getElementType(typeSignature), typeParameters);
	}
	
	/**
	 * these types can be arrays (e.g. "java.lang.String[]");
	 * but they won't have any further nested generic type arguments
	 * (e.g. "java.util.Collection<java.lang.String>")
	 */
	static List<String> convertTypeSignatureToTypeTypeArgumentNames(String typeSignature, Iterable<ITypeParameter> typeParameters) {
		if (typeSignature == null) {
			return Collections.emptyList();
		}
		
		String[] typeArgumentSignatures = Signature.getTypeArguments(typeSignature);
		if (typeArgumentSignatures.length == 0) {
			return Collections.emptyList();
		}
		
		ArrayList<String> names = new ArrayList<String>(typeArgumentSignatures.length);
		for (String typeArgumentSignature : typeArgumentSignatures) {
			names.add(convertTypeSignatureToTypeName(typeArgumentSignature, typeParameters));
		}
		return names;
	}
	
	public boolean isPublicOrProtected() {
		return this.isPublic() || this.isProtected();
	}
	
	// ********** IMember adapter **********

	interface Adapter extends BinaryAnnotatedElement.Adapter {
		/**
		 * Return the adapter's JDT member (IType, IField, IMethod).
		 */
		IMember getElement();
		
		Iterable<ITypeParameter> getTypeParameters();
	}


	// ********** unsupported JavaResourceMember implementation **********

	public Annotation setPrimaryAnnotation(String primaryAnnotationName, Iterable<String> supportingAnnotationNames) {
		throw new UnsupportedOperationException();
	}

	public void resolveTypes(CompilationUnit astRoot) {
		throw new UnsupportedOperationException();
	}

	public boolean isFor(String memberName, int occurrence) {
		throw new UnsupportedOperationException();
	}
}
