/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.javac.typemodel;

import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.collect.Lists;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

/**
 * Common superclass for {@link JMethod} and {@link JConstructor}.
 */
public abstract class JAbstractMethod implements
    com.google.gwt.core.ext.typeinfo.JAbstractMethod {

  private final Annotations annotations;

  private boolean isVarArgs = false;

  private int modifierBits;

  private final String name;

  private List<JParameter> params = Lists.create();

  private String[] realParameterNames = null;

  private List<JClassType> thrownTypes = Lists.create();

  private List<JTypeParameter> typeParams = Lists.create();

  JAbstractMethod(JAbstractMethod srcMethod) {
    this.annotations = new Annotations(srcMethod.annotations);
    this.isVarArgs = srcMethod.isVarArgs;
    this.modifierBits = srcMethod.modifierBits;
    this.name = srcMethod.name;
  }

  // Only the builder can construct
  JAbstractMethod(String name,
      Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
      JTypeParameter[] jtypeParameters) {
    this.name = StringInterner.get().intern(name);
    annotations = new Annotations(declaredAnnotations);

    if (jtypeParameters != null) {
      typeParams = Lists.create(jtypeParameters);
    }
  }

  public JParameter findParameter(String name) {
    for (JParameter param : params) {
      if (param.getName().equals(name)) {
        return param;
      }
    }
    return null;
  }

  public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
    return annotations.getAnnotation(annotationClass);
  }

  public Annotation[] getAnnotations() {
    return annotations.getAnnotations();
  }

  public Annotation[] getDeclaredAnnotations() {
    return annotations.getDeclaredAnnotations();
  }

  /**
   * Gets the type in which this method or constructor was declared.
   */
  public abstract JClassType getEnclosingType();

  public JType[] getErasedParameterTypes() {
    JType[] types = new JType[params.size()];
    for (int i = 0; i < types.length; ++i) {
      types[i] = params.get(i).getType().getErasedType();
    }
    return types;
  }

  /**
   * Returns a string contating a JSNI reference to the method.
   * 
   * @return <code>@package.Class::method(Lpackage/Param;...)</code>
   */
  public abstract String getJsniSignature();

  @Deprecated
  public final String[][] getMetaData(String tagName) {
    return TypeOracle.NO_STRING_ARR_ARR;
  }

  @Deprecated
  public final String[] getMetaDataTags() {
    return TypeOracle.NO_STRINGS;
  }

  public String getName() {
    return name;
  }

  public JParameter[] getParameters() {
    // TODO(jat): where do we handle fake arg names?
    return params.toArray(TypeOracle.NO_JPARAMS);
  }

  public JType[] getParameterTypes() {
    final JType[] paramTypes = new JType[params.size()];
    for (int i = 0; i < paramTypes.length; ++i) {
      paramTypes[i] = params.get(i).getType();
    }
    return paramTypes;
  }

  public abstract String getReadableDeclaration();

  public JClassType[] getThrows() {
    return thrownTypes.toArray(TypeOracle.NO_JCLASSES);
  }

  public JTypeParameter[] getTypeParameters() {
    return typeParams.toArray(new JTypeParameter[typeParams.size()]);
  }

  public JAnnotationMethod isAnnotationMethod() {
    return null;
  }

  public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
    return annotations.isAnnotationPresent(annotationClass);
  }

  public abstract JConstructor isConstructor();

  public boolean isDefaultAccess() {
    return 0 == (modifierBits & (TypeOracle.MOD_PUBLIC | TypeOracle.MOD_PRIVATE | TypeOracle.MOD_PROTECTED));
  }

  public abstract JMethod isMethod();

  public boolean isPrivate() {
    return 0 != (modifierBits & TypeOracle.MOD_PRIVATE);
  }

  public boolean isProtected() {
    return 0 != (modifierBits & TypeOracle.MOD_PROTECTED);
  }

  public boolean isPublic() {
    return 0 != (modifierBits & TypeOracle.MOD_PUBLIC);
  }

  public boolean isVarArgs() {
    return isVarArgs;
  }

  protected int getModifierBits() {
    return modifierBits;
  }

  protected void toStringParamsAndThrows(StringBuilder sb) {
    sb.append("(");
    boolean needComma = false;
    for (int i = 0, c = params.size(); i < c; ++i) {
      JParameter param = params.get(i);
      if (needComma) {
        sb.append(", ");
      } else {
        needComma = true;
      }
      if (isVarArgs() && i == c - 1) {
        JArrayType arrayType = (JArrayType) param.getType().isArray();
        assert (arrayType != null);
        sb.append(arrayType.getComponentType().getParameterizedQualifiedSourceName());
        sb.append("...");
      } else {
        sb.append(param.getType().getParameterizedQualifiedSourceName());
      }
      sb.append(" ");
      sb.append(param.getName());
    }
    sb.append(")");

    if (!thrownTypes.isEmpty()) {
      sb.append(" throws ");
      needComma = false;
      for (JClassType thrownType : thrownTypes) {
        if (needComma) {
          sb.append(", ");
        } else {
          needComma = true;
        }
        sb.append(thrownType.getParameterizedQualifiedSourceName());
      }
    }
  }

  protected void toStringTypeParams(StringBuilder sb) {
    sb.append("<");
    boolean needComma = false;
    for (JTypeParameter typeParam : typeParams) {
      if (needComma) {
        sb.append(", ");
      } else {
        needComma = true;
      }
      sb.append(typeParam.getQualifiedSourceName());
    }
    sb.append(">");
  }

  void addModifierBits(int bits) {
    modifierBits |= bits;
  }

  void addParameter(JParameter param) {
    params = Lists.add(params, param);
  }

  void addThrows(JClassType type) {
    thrownTypes = Lists.add(thrownTypes, type);
  }

  // Called only by a JParameter, passing itself as a reference for lookup.
  String getRealParameterName(JParameter parameter) {
    if (realParameterNames == null) {
      fetchRealParameterNames();
    }
    int n = params.size();
    for (int i = 0; i < n; ++i) {
      // Identity tests are ok since identity is durable within an oracle.
      if (params.get(i) == parameter) {
        String realParameterName;
        if (realParameterNames == null) {
          realParameterName = StringInterner.get().intern("arg" + i);
        } else {
          realParameterName = StringInterner.get().intern(realParameterNames[i]);
        }
        return realParameterName;
      }
    }
    // TODO: report error if we are asked for an unknown JParameter?
    return null;
  }

  boolean hasParamTypes(JType[] paramTypes) {
    if (params.size() != paramTypes.length) {
      return false;
    }

    for (int i = 0; i < paramTypes.length; i++) {
      JParameter candidate = params.get(i);
      // Identity tests are ok since identity is durable within an oracle.
      //
      if (candidate.getType() != paramTypes[i]) {
        return false;
      }
    }
    return true;
  }

  void setVarArgs() {
    isVarArgs = true;
  }

  private void fetchRealParameterNames() {
    realParameterNames = getEnclosingType().getOracle().getJavaSourceParser().getArguments(
        this);
  }
}
