/*
 * Copyright 2009 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;

import com.google.gwt.core.client.impl.ArtificialRescue;
import com.google.gwt.dev.jdt.SafeASTVisitor;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.dev.util.collect.Lists;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

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

/**
 * Checks the validity of ArtificialRescue annotations.
 * 
 * <ul>
 * <li>(1) The ArtificialRescue annotation is only used in generated code.</li>
 * <li>(2) The className value names a type known to GWT.</li>
 * <li>(3) The methods and fields of the type are known to GWT.</li>
 * </ul>
 */
public abstract class ArtificialRescueChecker {

  /**
   * Represents a single
   * {@link com.google.gwt.core.client.impl.ArtificialRescue.Rescue}.
   * <p>
   * Only public so it can be used by
   * {@link com.google.gwt.dev.jjs.impl.GenerateJavaAST}.
   */
  public static class RescueData {
    private static final RescueData[] EMPTY_RESCUEDATA = new RescueData[0];

    public static RescueData[] createFromAnnotations(Annotation[] annotations) {
      RescueData[] result = EMPTY_RESCUEDATA;
      for (Annotation a : annotations) {
        ReferenceBinding binding = (ReferenceBinding) a.resolvedType;
        String name = CharOperation.toString(binding.compoundName);
        if (!name.equals(ArtificialRescue.class.getName())) {
          continue;
        }
        return createFromArtificialRescue(a);
      }
      return result;
    }

    public static RescueData[] createFromArtificialRescue(Annotation artificialRescue) {
      Object[] values = null;
      RescueData[] result = EMPTY_RESCUEDATA;
      for (ElementValuePair pair : artificialRescue.computeElementValuePairs()) {
        if ("value".equals(String.valueOf(pair.getName()))) {
          Object value = pair.getValue();
          if (value instanceof AnnotationBinding) {
            values = new Object[]{value};
          } else {
            values = (Object[]) value;
          }
          break;
        }
      }
      assert values != null;
      if (values.length > 0) {
        result = new RescueData[values.length];
        for (int i = 0; i < result.length; ++i) {
          result[i] = createFromRescue((AnnotationBinding) values[i]);
        }
      }
      return result;
    }

    private static RescueData createFromRescue(AnnotationBinding rescue) {
      String className = null;
      boolean instantiable = false;
      String[] methods = Empty.STRINGS;
      String[] fields = Empty.STRINGS;
      for (ElementValuePair pair : rescue.getElementValuePairs()) {
        String name = String.valueOf(pair.getName());
        if ("className".equals(name)) {
          className = ((StringConstant) pair.getValue()).stringValue();
        } else if ("instantiable".equals(name)) {
          BooleanConstant value = (BooleanConstant) pair.getValue();
          instantiable = value.booleanValue();
        } else if ("methods".equals(name)) {
          methods = getValueAsStringArray(pair.getValue());
        } else if ("fields".equals(name)) {
          fields = getValueAsStringArray(pair.getValue());
        } else {
          assert false : "Unknown ArtificialRescue field";
        }
      }
      assert className != null;
      return new RescueData(className, instantiable, fields, methods);
    }

    private static String[] getValueAsStringArray(Object value) {
      if (value instanceof StringConstant) {
        return new String[]{((StringConstant) value).stringValue()};
      }
      Object[] values = (Object[]) value;
      String[] toReturn = new String[values.length];
      for (int i = 0; i < toReturn.length; ++i) {
        toReturn[i] = ((StringConstant) values[i]).stringValue();
      }
      return toReturn;
    }

    private final String className;
    private final String[] fields;
    private final boolean instantiable;
    private final String[] methods;

    RescueData(String className, boolean instantiable, String[] fields, String[] methods) {
      this.className = className;
      this.instantiable = instantiable;
      this.methods = methods;
      this.fields = fields;
    }

    public String getClassName() {
      return className;
    }

    public String[] getFields() {
      return fields;
    }

    public String[] getMethods() {
      return methods;
    }

    public boolean isInstantiable() {
      return instantiable;
    }
  }

  /**
   * Checks that references are legal and resolve to a known element. Collects
   * the rescued elements per type for later user.
   */
  private static class Checker extends ArtificialRescueChecker {
    private final Map<TypeDeclaration, Binding[]> artificialRescues;
    private transient List<Binding> currentBindings = new ArrayList<Binding>();

    public Checker(CompilationUnitDeclaration cud, Map<TypeDeclaration, Binding[]> artificialRescues) {
      super(cud);
      this.artificialRescues = artificialRescues;
    }

    @Override
    protected void processRescue(RescueData rescue) {
      String className = rescue.getClassName();
      // Strip off any array-like extensions and just find base type
      int arrayDims = 0;
      while (className.endsWith("[]")) {
        className = className.substring(0, className.length() - 2);
        ++arrayDims;
      }

      // Goal (2) The className value names a type known to GWT.
      char[][] compoundName = CharOperation.splitOn('.', className.toCharArray());
      TypeBinding typeBinding = cud.scope.getType(compoundName, compoundName.length);
      if (typeBinding == null) {
        error(notFound(className));
        return;
      }
      if (typeBinding instanceof ProblemReferenceBinding) {
        ProblemReferenceBinding problem = (ProblemReferenceBinding) typeBinding;
        if (problem.problemId() == ProblemReasons.NotVisible) {
          // Ignore
        } else if (problem.problemId() == ProblemReasons.NotFound) {
          error(notFound(className));
        } else {
          error(unknownProblem(className, problem));
        }
        return;
      }
      if (arrayDims > 0) {
        typeBinding = cud.scope.createArrayType(typeBinding, arrayDims);
      }
      if (rescue.isInstantiable()) {
        currentBindings.add(typeBinding);
      }
      if (typeBinding instanceof BaseTypeBinding || arrayDims > 0) {
        // No methods or fields on primitive types or array types (3)
        if (rescue.getMethods().length > 0) {
          error(noMethodsAllowed());
        }

        if (rescue.getFields().length > 0) {
          error(noFieldsAllowed());
        }
        return;
      }

      // Goal (3) The methods and fields of the type are known to GWT.
      ReferenceBinding ref = (ReferenceBinding) typeBinding;
      for (String field : rescue.getFields()) {
        FieldBinding fieldBinding = ref.getField(field.toCharArray(), false);
        if (fieldBinding == null) {
          error(unknownField(field));
        } else {
          currentBindings.add(fieldBinding);
        }
      }
      for (String method : rescue.getMethods()) {
        if (method.contains("@")) {
          error(nameAndTypesOnly());
          continue;
        }
        // Method signatures use the same format as JSNI method refs.
        JsniRef jsni = JsniRef.parse("@foo::" + method);
        if (jsni == null) {
          error(badMethodSignature(method));
          continue;
        }

        MethodBinding[] methodBindings;
        if (jsni.memberName().equals(String.valueOf(ref.compoundName[ref.compoundName.length - 1]))) {
          // Constructor
          methodBindings = ref.getMethods("<init>".toCharArray());
        } else {
          methodBindings = ref.getMethods(jsni.memberName().toCharArray());
        }
        boolean found = false;
        for (MethodBinding methodBinding : methodBindings) {
          if (jsni.matchesAnyOverload() || jsni.paramTypesString().equals(sig(methodBinding))) {
            currentBindings.add(methodBinding);
            found = true;
          }
        }
        if (!found) {
          error(noMethod(className, jsni.memberSignature()));
          continue;
        }
      }
    }

    @Override
    protected void processType(TypeDeclaration x) {
      super.processType(x);
      if (currentBindings.size() > 0) {
        Binding[] result = currentBindings.toArray(new Binding[currentBindings.size()]);
        artificialRescues.put(x, result);
        currentBindings = new ArrayList<Binding>();
      }
    }

    private String sig(MethodBinding methodBinding) {
      StringBuilder sb = new StringBuilder();
      for (TypeBinding paramType : methodBinding.parameters) {
        sb.append(paramType.signature());
      }
      return sb.toString();
    }
  }

  /**
   * Collects only the names of the rescued types; does not report errors.
   */
  private static class Collector extends ArtificialRescueChecker {
    private final List<String> referencedTypes;

    public Collector(CompilationUnitDeclaration cud, List<String> referencedTypes) {
      super(cud);
      this.referencedTypes = referencedTypes;
    }

    @Override
    protected void processRescue(RescueData rescue) {
      String className = rescue.getClassName();
      while (className.endsWith("[]")) {
        className = className.substring(0, className.length() - 2);
      }
      referencedTypes.add(className);
    }
  }

  /**
   * Records an error if artificial rescues are used at all.
   */
  private static class Disallowed extends ArtificialRescueChecker {
    public Disallowed(CompilationUnitDeclaration cud) {
      super(cud);
    }

    @Override
    protected void processRescue(RescueData rescue) {
      // Goal (1) ArtificialRescue annotation is only used in generated code.
      error(onlyGeneratedCode());
    }
  }

  private class Visitor extends SafeASTVisitor {
    @Override
    public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
      processType(memberTypeDeclaration);
    }

    @Override
    public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
      processType(typeDeclaration);
    }

    @Override
    public void endVisitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
      processType(localTypeDeclaration);
    }
  }

  /**
   * Check the {@link ArtificialRescue} annotations in a CompilationUnit. Errors
   * are reported through {@link GWTProblem}.
   */
  public static void check(CompilationUnitDeclaration cud, boolean allowArtificialRescue,
      Map<TypeDeclaration, Binding[]> artificialRescues) {
    if (allowArtificialRescue) {
      new Checker(cud, artificialRescues).exec();
    } else {
      new Disallowed(cud).exec();
    }
  }

  /**
   * Report all types named in {@link ArtificialRescue} annotations in a CUD. No
   * error checking is done.
   */
  public static List<String> collectReferencedTypes(CompilationUnitDeclaration cud) {
    ArrayList<String> result = new ArrayList<String>();
    new Collector(cud, result).exec();
    return Lists.normalize(result);
  }

  static String badMethodSignature(String method) {
    return "Bad method signature " + method;
  }

  static String nameAndTypesOnly() {
    return "Only method name and parameter types expected";
  }

  static String noFieldsAllowed() {
    return "Cannot refer to fields on array or primitive types";
  }

  static String noMethod(String className, String methodSig) {
    return "No method " + methodSig + " in type " + className;
  }

  static String noMethodsAllowed() {
    return "Cannot refer to methods on array or primitive types";
  }

  static String notFound(String className) {
    return "Could not find type " + className;
  }

  static String onlyGeneratedCode() {
    return "The " + ArtificialRescue.class.getName()
        + " annotation may only be used in generated code and its use"
        + " by third parties is not supported.";
  }

  static String unknownField(String field) {
    return "Unknown field " + field;
  }

  static String unknownProblem(String className, ProblemReferenceBinding problem) {
    return "Unknown problem: " + ProblemReferenceBinding.problemReasonString(problem.problemId())
        + " " + className;
  }

  protected final CompilationUnitDeclaration cud;

  private Annotation errorNode;

  private ArtificialRescueChecker(CompilationUnitDeclaration cud) {
    this.cud = cud;
  }

  protected final void error(String msg) {
    GWTProblem.recordError(errorNode, cud, msg, null);
  }

  protected final void exec() {
    cud.traverse(new Visitor(), cud.scope);
  }

  protected abstract void processRescue(RescueData rescue);

  /**
   * Examine a TypeDeclaration for ArtificialRescue annotations.
   */
  protected void processType(TypeDeclaration x) {
    if (x.annotations == null) {
      return;
    }
    for (Annotation a : x.annotations) {
      ReferenceBinding binding = (ReferenceBinding) a.resolvedType;
      String name = CharOperation.toString(binding.compoundName);
      if (!name.equals(ArtificialRescue.class.getName())) {
        continue;
      }
      errorNode = a;
      RescueData[] rescues = RescueData.createFromArtificialRescue(a);
      for (RescueData rescue : rescues) {
        processRescue(rescue);
      }
      break;
    }
  }
}
