package jp.sourceforge.asclipse.as3.internal.element;

import java.util.Collections;
import java.util.List;

import jp.sourceforge.asclipse.as3.element.AS3Function;
import jp.sourceforge.asclipse.as3.element.AS3Variable;
import jp.sourceforge.asclipse.as3.resolver.AS3TypeRef;
import jp.sourceforge.asclipse.as3.util.ModifiersUtil;
import jp.sourceforge.asclipse.as3.util.CommonTreeUtil.SerializableToken;

import org.antlr.runtime.tree.CommonTree;
import org.apache.commons.lang.StringUtils;

/**
 * {@link DefaultAS3Function}の内部用の実装。
 * @author shin1ogawa
 */
@SuppressWarnings("serial")
public class DefaultAS3Function extends AbstractAS3ElementWithModifiers implements AS3Function {

	private final SerializableToken accessor;

	private final String identifier;

	private final List<AS3Variable> parameters;

	private final AS3TypeRef typeRef;


	/**
	 * Constructor.
	 * @param tree
	 * @param modifiers
	 * @param accessor
	 * @param identifier
	 * @param parameters
	 * @param typeRef
	 * @category constructor
	 */
	public DefaultAS3Function(CommonTree tree, CommonTree[] modifiers, CommonTree accessor,
			String identifier, List<AS3Variable> parameters, AS3TypeRef typeRef) {
		super(tree, modifiers);
		this.accessor = accessor != null ? new SerializableToken(accessor.getToken()) : null;
		this.identifier = identifier;
		this.parameters = parameters;
		this.typeRef = typeRef;
	}

	public String getOutlineTitle() {
		StringBuilder b = new StringBuilder();
		b.append(accessor != null ? accessor.getText() + " " : "");
		b.append(identifier);
		b.append("(");
		boolean first = true;
		for (AS3Variable variable : parameters) {
			if (!first) {
				b.append(",");
			} else {
				first = false;
			}
			b.append(variable.getTypeRef().getTypeName());
		}
		b.append(")");
		if (typeRef != AS3TypeRef.NULL_TYPE_REF) {
			b.append(":").append(typeRef.getTypeName());
		}
		return b.toString();
	}

	public String getTitle() {
		StringBuilder b = new StringBuilder();
		b.append(ModifiersUtil.getTitle(modifiers));
		b.append(b.length() == 0 ? "" : " ").append("function ");
		b.append(accessor != null ? accessor.getText() + " " : "");
		b.append(identifier);
		b.append("(");
		boolean first = true;
		for (AS3Variable variable : parameters) {
			if (!first) {
				b.append(", ");
			} else {
				first = false;
			}
			b.append(variable.getTitle());
		}
		b.append(")");
		if (typeRef != AS3TypeRef.NULL_TYPE_REF) {
			b.append(":").append(typeRef.getTypeName());
		}
		return b.toString();
	}

	public boolean isConstructor() {
		return StringUtils.isEmpty(typeRef.getTypeName())
				&& (getEnclosureType() != null && getEnclosureType().getIdentifier().equals(
						identifier));
	}

	public AccessorType getAccessorType() {
		return AccessorType.valueOf(accessor != null ? accessor : null /* exception*/);
	}

	public AS3TypeRef getTypeRef() {
		return typeRef;
	}

	public List<AS3Variable> getParameters() {
		return Collections.unmodifiableList(parameters);
	}

	public boolean isAccessor() {
		return accessor != null;
	}

	public String getIdentifier() {
		return identifier;
	}
}
