/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.android.jack.ecj.loader.jast;

import com.android.jack.ir.ast.HasEnclosingMethod;
import com.android.jack.ir.ast.JAbstractStringLiteral;
import com.android.jack.ir.ast.JAnnotation;
import com.android.jack.ir.ast.JClass;
import com.android.jack.ir.ast.JClassOrInterface;
import com.android.jack.ir.ast.JDefinedClass;
import com.android.jack.ir.ast.JDefinedClassOrInterface;
import com.android.jack.ir.ast.JDefinedInterface;
import com.android.jack.ir.ast.JField;
import com.android.jack.ir.ast.JIntLiteral;
import com.android.jack.ir.ast.JInterface;
import com.android.jack.ir.ast.JLiteral;
import com.android.jack.ir.ast.JMethod;
import com.android.jack.ir.ast.JNameValuePair;
import com.android.jack.ir.ast.JNullLiteral;
import com.android.jack.ir.ast.marker.SimpleName;
import com.android.jack.ir.formatter.TypeFormatter;
import com.android.jack.ir.sourceinfo.SourceInfo;
import com.android.jack.util.NamingTools;

import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

/**
 * A {@code IBinaryType} for jack.
 */
class JAstBinaryType implements IBinaryType {

  @Nonnull
  private static final char[] OBJECT = "java/lang/Object".toCharArray();

  @Nonnull
  private final JDefinedClassOrInterface jDeclaredType;
  @Nonnull
  private final JAstClasspath classpathLocation;

  JAstBinaryType(
      @Nonnull JDefinedClassOrInterface jDeclaredType, @Nonnull JAstClasspath classpathLocation) {
    this.jDeclaredType = jDeclaredType;
    this.classpathLocation = classpathLocation;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int getModifiers() {
    int modifiers;
    JAnnotation enclosingAnnotation =
        AnnotationUtils.getAnnotation(jDeclaredType, AnnotationUtils.INNER_CLASS_ANNOTATION);
    if (enclosingAnnotation != null) {
      JNameValuePair pair =
          enclosingAnnotation.getNameValuePair(AnnotationUtils.INNERCLASS_ACCFLAGS_FIELD);
      assert pair != null;
      modifiers = ((JIntLiteral) pair.getValue()).getIntValue();
    } else {
      modifiers = jDeclaredType.getModifier();
    }
    modifiers = LoaderUtils.convertJAstModifiersToEcj(modifiers, jDeclaredType);

    JClassOrInterface enclosingType = jDeclaredType.getEnclosingType();
    if (enclosingType != null && !isAnonymous()
        && enclosingType instanceof JDefinedClassOrInterface) {
      /* If the enclosing is not in the classpath, just skip. This should be with no bad consequence
       * since ECJ is refusing to compile a source referencing an inner class when its enclosing
       * class is missing.
       */
      JAstBinaryType enclosing =
          classpathLocation.findType((JDefinedClassOrInterface) enclosingType);
      if (enclosing != null) {
        if (LoaderUtils.isDeprecated(enclosing)) {
          modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
        }
      }
    }

    return modifiers;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isBinaryType() {
    return true;
  }

  /**
   * {@inheritDoc}
   */
  @Nonnull
  @Override
  public char[] getFileName() {
    return (classpathLocation.getPath() + "|" + getBinaryName()).toCharArray();
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public IBinaryAnnotation[] getAnnotations() {
    return AnnotationUtils.convertJAstAnnotationToEcj(jDeclaredType, true);
  }

  public boolean hasEnclosingMethod() {
    return jDeclaredType instanceof JDefinedClass
        && ((JDefinedClass) jDeclaredType).getEnclosingMethod() != null;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[] getEnclosingTypeName() {
    char[] enclosingTypeName = null;
    JClassOrInterface enclosingType = jDeclaredType.getEnclosingType();
    if (enclosingType == null && jDeclaredType instanceof JDefinedClass) {

      JMethod enclosingMethod = ((JDefinedClass) jDeclaredType).getEnclosingMethod();
      if (enclosingMethod != null) {
        enclosingType = enclosingMethod.getEnclosingType();
      }
    }
    if (enclosingType != null) {
      enclosingTypeName =
          LoaderUtils.getQualifiedNameFormatter().getName(enclosingType).toCharArray();
    }
    return enclosingTypeName;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public IBinaryField[] getFields() {
    List<JField> fields = jDeclaredType.getFields();
    int totalFields = fields.size();

    if (totalFields == 0) {
      return null;
    }
    IBinaryField[] allFields = new IBinaryField[totalFields];
    int indexInAllFields = 0;
    for (JField field : fields) {
      JLiteral initialValue = null;
      initialValue = field.getLiteralInitializer();
      if (initialValue == null) {
        initialValue = field.getInitialValue();
      }
      allFields[indexInAllFields] = new JAstBinaryField(field, initialValue);
      indexInAllFields++;
    }

    return allFields;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[] getGenericSignature() {
    return LoaderUtils.getGenericSignature(jDeclaredType);
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[][] getInterfaceNames() {
    List<JInterface> implemented = jDeclaredType.getImplements();
    char[][] names = null;
    int interfaceCount = implemented.size();
    if (interfaceCount > 0) {
      names = new char[interfaceCount][];
      TypeFormatter formatter = LoaderUtils.getQualifiedNameFormatter();
      for (int i = 0; i < interfaceCount; i++) {
        names[i] = formatter.getName(implemented.get(i)).toCharArray();
      }
    }
    return names;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public IBinaryNestedType[] getMemberTypes() {
    List<JClassOrInterface> members = jDeclaredType.getMemberTypes();

    IBinaryNestedType[] nestedTypesArray = null;

    if (!members.isEmpty()) {
       int nestedTypeCount = members.size();
      List<IBinaryNestedType> nestedTypes = new ArrayList<IBinaryNestedType>(nestedTypeCount);

      for (JClassOrInterface jNested : members) {

        /* If the inner is not in the classpath, just skip it. This should not have consequence in
         * Jack context, since we are unable to present the missing class to ECJ anyway. */
        if (jNested instanceof JDefinedClassOrInterface) {
          /* According to a note in a comment on the interface, we have to filter out local types
           * found in the member types list. Tests have shown that, in this note, "local" means also
           * anonymous.
           */
          JAstBinaryType nested = classpathLocation.findType((JDefinedClassOrInterface) jNested);
          assert nested != null;
          if (!(nested.isAnonymous() || nested.isLocal())) {
            nestedTypes.add(new JAstBinaryNestedType(nested.jDeclaredType));
          }
        }
      }
      if (!nestedTypes.isEmpty()) {
        nestedTypesArray = nestedTypes.toArray(new IBinaryNestedType[nestedTypes.size()]);
      }
    }

    return nestedTypesArray;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public IBinaryMethod[] getMethods() {
    List<JMethod> jMethods = jDeclaredType.getMethods();
    int total = jMethods.size();
    IBinaryMethod[] methods = null;
      if (total != 0) {
        methods = new IBinaryMethod[total];
        int indexInMethods = 0;
        for (JMethod method: jMethods) {
          methods[indexInMethods] = new JAstBinaryMethod(method);
          indexInMethods++;
        }
    }

    return methods;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[][][] getMissingTypeNames() {
    // N/A (Eclipse compiled classes with errors)
    return null;
  }

  /**
   * {@inheritDoc}
   */
  @Nonnull
  @Override
  public char[] getName() {
    return getBinaryName().toCharArray();
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[] getSourceName() {

    SimpleName typeInfo = jDeclaredType.getMarker(SimpleName.class);
    if (typeInfo != null) {
      return typeInfo.getSimpleName().toCharArray();
    }

    char[] sourceNameArray;
    JAnnotation enclosingAnnotation =
        AnnotationUtils.getAnnotation(jDeclaredType, AnnotationUtils.INNER_CLASS_ANNOTATION);
    if (enclosingAnnotation != null) {

      /* if this class is an inner then return the source name given by the annotation */
      JNameValuePair pair =
          enclosingAnnotation.getNameValuePair(AnnotationUtils.INNERCLASS_NAME_FIELD);
      assert pair != null : "Invalid jayce file";
      JLiteral nameValue = pair.getValue();
      if (nameValue instanceof JNullLiteral) {
        /*
         * javadoc says anonymous must return null but ClassFileReader returns a name. Anyway
         * ClassFileReader returns weird things with anonymous in inner. Lets stick to the javadoc
         * for now. If we decide to stick to the reference instead we could just subtract the
         * enclosingTypeName to this type name.
         */
        sourceNameArray = null;
      } else {
        String sourceName = ((JAbstractStringLiteral) nameValue).getValue();
        sourceNameArray = sourceName.toCharArray();
      }

    } else {
      String binaryName = getBinaryName();
      String simpleName = NamingTools.getSimpleClassNameFromBinaryName(binaryName);
      sourceNameArray = simpleName.toCharArray();
    }

    return sourceNameArray;
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[] getSuperclassName() {
    JClass superType = jDeclaredType.getSuperClass();
    if (superType != null) {
      return LoaderUtils.getQualifiedNameFormatter().getName(superType).toCharArray();
    } else if (jDeclaredType instanceof JDefinedInterface) {
      return OBJECT;
    } else {
      return null;
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public long getTagBits() {
    return AnnotationUtils.getTagBits(jDeclaredType);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isAnonymous() {
    boolean isAnonymous = false;
    SimpleName simpleNameInfo = jDeclaredType.getMarker(SimpleName.class);
    if (simpleNameInfo != null) {
      isAnonymous = simpleNameInfo.getSimpleName().isEmpty();
    } else {
      JAnnotation enclosingAnnotation =
          AnnotationUtils.getAnnotation(jDeclaredType, AnnotationUtils.INNER_CLASS_ANNOTATION);
      if (enclosingAnnotation != null) {
        JNameValuePair pair =
            enclosingAnnotation.getNameValuePair(AnnotationUtils.INNERCLASS_NAME_FIELD);
        assert pair != null;
        isAnonymous = (pair.getValue() instanceof JNullLiteral);
      }
    }

    return isAnonymous;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isLocal() {
    return (!isAnonymous()) && hasEnclosingMethod();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isMember() {
    return (!isAnonymous())
        && (jDeclaredType.getEnclosingType() != null && !hasEnclosingMethod());
  }

  /**
   * {@inheritDoc}
   */
  @CheckForNull
  @Override
  public char[] sourceFileName() {
    if (jDeclaredType.getSourceInfo() == SourceInfo.UNKNOWN) {
      return null;
    }
    String fileName = jDeclaredType.getSourceInfo().getFileName();
    int simpleNameIndex = fileName.lastIndexOf('/');
    simpleNameIndex = Math.max(simpleNameIndex, fileName.lastIndexOf('\\'));
    if (simpleNameIndex > 0) {
      fileName = fileName.substring(simpleNameIndex + 1);
    }

    return fileName.toCharArray();

  }

  @Override
  @Nonnull
  public String toString() {
    return jDeclaredType.toString();
  }

  @Nonnull
  String getBinaryName() {
    return LoaderUtils.getQualifiedNameFormatter().getName(jDeclaredType);
  }

  @Override
  public char[] getEnclosingMethod() {
    char[] enclosingMethodName = null;

    if (jDeclaredType instanceof HasEnclosingMethod) {
      JMethod enclosingMethod = ((HasEnclosingMethod) jDeclaredType).getEnclosingMethod();
      if (enclosingMethod != null) {
        enclosingMethodName =
            LoaderUtils.getSignatureFormatter().getName(enclosingMethod).toCharArray();
      }
    }

    return enclosingMethodName;
  }

  @Override
  public IBinaryTypeAnnotation[] getTypeAnnotations() {
    return null;
  }

  @Override
  public ITypeAnnotationWalker enrichWithExternalAnnotationsFor(ITypeAnnotationWalker walker,
      Object member, LookupEnvironment environment) {
    // Jack does not support ecj external annotation file
    return walker;
  }

  @Override
  public ExternalAnnotationStatus getExternalAnnotationStatus() {
    return ExternalAnnotationStatus.FROM_SOURCE;
  }
}
