/*
 * Copyright 2010 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.web.bindery.autobean.gwt.rebind.model;

import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanFactory;
import com.google.web.bindery.autobean.shared.AutoBeanFactory.Category;
import com.google.web.bindery.autobean.shared.AutoBeanFactory.NoWrap;
import com.google.web.bindery.autobean.shared.impl.EnumMap.ExtraEnums;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.rebind.model.ModelUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 
 */
public class AutoBeanFactoryModel {
  private static final JType[] EMPTY_JTYPE = new JType[0];

  private final JGenericType autoBeanInterface;
  private final JClassType autoBeanFactoryInterface;
  private final Map<JEnumConstant, String> allEnumConstants = new LinkedHashMap<JEnumConstant, String>();
  private final List<JClassType> categoryTypes;
  private final List<JClassType> noWrapTypes;
  private final TreeLogger logger;
  private final List<AutoBeanFactoryMethod> methods = new ArrayList<AutoBeanFactoryMethod>();
  private final List<JMethod> objectMethods;
  private final TypeOracle oracle;
  private final Map<JClassType, AutoBeanType> peers = new LinkedHashMap<JClassType, AutoBeanType>();
  private boolean poisoned;

  /**
   * Accumulates bean types that are reachable through the type graph.
   */
  private Set<JClassType> toCalculate = new LinkedHashSet<JClassType>();

  public AutoBeanFactoryModel(TreeLogger logger, JClassType factoryType)
      throws UnableToCompleteException {
    this.logger = logger;
    oracle = factoryType.getOracle();
    autoBeanInterface = oracle.findType(AutoBean.class.getCanonicalName()).isGenericType();
    autoBeanFactoryInterface = oracle.findType(
        AutoBeanFactory.class.getCanonicalName()).isInterface();

    /*
     * We want to allow the user to override some of the useful Object methods,
     * so we'll extract them here.
     */
    JClassType objectType = oracle.getJavaLangObject();
    objectMethods = Arrays.asList(
        objectType.findMethod("equals", new JType[] {objectType}),
        objectType.findMethod("hashCode", EMPTY_JTYPE),
        objectType.findMethod("toString", EMPTY_JTYPE));

    // Process annotations
    {
      Category categoryAnnotation = factoryType.getAnnotation(Category.class);
      if (categoryAnnotation != null) {
        categoryTypes = new ArrayList<JClassType>(
            categoryAnnotation.value().length);
        processClassArrayAnnotation(categoryAnnotation.value(), categoryTypes);
      } else {
        categoryTypes = null;
      }

      noWrapTypes = new ArrayList<JClassType>();
      noWrapTypes.add(oracle.findType(AutoBean.class.getCanonicalName()));
      NoWrap noWrapAnnotation = factoryType.getAnnotation(NoWrap.class);
      if (noWrapAnnotation != null) {
        processClassArrayAnnotation(noWrapAnnotation.value(), noWrapTypes);
      }

      ExtraEnums extraEnumsAnnotation = factoryType.getAnnotation(ExtraEnums.class);
      if (extraEnumsAnnotation != null) {
        for (Class<?> clazz : extraEnumsAnnotation.value()) {
          JEnumType asEnum = oracle.findType(clazz.getCanonicalName()).isEnum();
          assert asEnum != null;
          for (JEnumConstant value : asEnum.getEnumConstants()) {
            allEnumConstants.put(value, AutoBeanMethod.getEnumName(value));
          }
        }
      }
    }

    for (JMethod method : factoryType.getOverridableMethods()) {
      if (method.getEnclosingType().equals(autoBeanFactoryInterface)) {
        // Ignore methods in AutoBeanFactory
        continue;
      }

      JClassType returnType = method.getReturnType().isInterface();
      if (returnType == null) {
        poison("The return type of method %s is a primitive type",
            method.getName());
        continue;
      }

      // AutoBean<FooIntf> blah() --> beanType = FooIntf
      JClassType beanType = ModelUtils.findParameterizationOf(
          autoBeanInterface, returnType)[0];
      if (beanType.isInterface() == null) {
        poison("The %s parameterization is not an interface",
            beanType.getQualifiedSourceName());
        continue;
      }

      // AutoBean<FooIntf> blah(FooIntfSub foo) --> toWrap = FooIntfSub
      JClassType toWrap;
      if (method.getParameters().length == 0) {
        toWrap = null;
      } else if (method.getParameters().length == 1) {
        toWrap = method.getParameters()[0].getType().isClassOrInterface();
        if (!beanType.isAssignableFrom(toWrap)) {
          poison(
              "The %s parameterization %s is not assignable from the delegate"
                  + " type %s", autoBeanInterface.getSimpleSourceName(),
              toWrap.getQualifiedSourceName());
          continue;
        }
      } else {
        poison("Unexpecetd parameters in method %s", method.getName());
        continue;
      }

      AutoBeanType autoBeanType = getAutoBeanType(beanType);

      // Must wrap things that aren't simple interfaces
      if (!autoBeanType.isSimpleBean() && toWrap == null) {
        if (categoryTypes != null) {
          poison("The %s parameterization is not simple and the following"
              + " methods did not have static implementations:",
              beanType.getQualifiedSourceName());
          for (AutoBeanMethod missing : autoBeanType.getMethods()) {
            if (missing.getAction().equals(JBeanMethod.CALL)
                && missing.getStaticImpl() == null) {
              poison(missing.getMethod().getReadableDeclaration());
            }
          }
        } else {
          poison("The %s parameterization is not simple, but the %s method"
              + " does not provide a delegate",
              beanType.getQualifiedSourceName(), method.getName());
        }
        continue;
      }

      AutoBeanFactoryMethod.Builder builder = new AutoBeanFactoryMethod.Builder();
      builder.setAutoBeanType(autoBeanType);
      builder.setMethod(method);
      methods.add(builder.build());
    }

    while (!toCalculate.isEmpty()) {
      Set<JClassType> examine = toCalculate;
      toCalculate = new LinkedHashSet<JClassType>();
      for (JClassType beanType : examine) {
        getAutoBeanType(beanType);
      }
    }

    if (poisoned) {
      die("Unable to complete due to previous errors");
    }
  }

  public Collection<AutoBeanType> getAllTypes() {
    return Collections.unmodifiableCollection(peers.values());
  }

  public List<JClassType> getCategoryTypes() {
    return categoryTypes;
  }

  public Map<JEnumConstant, String> getEnumTokenMap() {
    return Collections.unmodifiableMap(allEnumConstants);
  }

  public List<AutoBeanFactoryMethod> getMethods() {
    return Collections.unmodifiableList(methods);
  }

  public AutoBeanType getPeer(JClassType beanType) {
    beanType = ModelUtils.ensureBaseType(beanType);
    return peers.get(beanType);
  }

  private List<AutoBeanMethod> computeMethods(JClassType beanType) {
    List<JMethod> toExamine = new ArrayList<JMethod>();
    toExamine.addAll(Arrays.asList(beanType.getInheritableMethods()));
    toExamine.addAll(objectMethods);
    List<AutoBeanMethod> toReturn = new ArrayList<AutoBeanMethod>(
        toExamine.size());
    for (JMethod method : toExamine) {
      if (method.isPrivate()) {
        // Ignore private methods
        continue;
      }
      AutoBeanMethod.Builder builder = new AutoBeanMethod.Builder();
      builder.setMethod(method);

      // See if this method shouldn't have its return type wrapped
      // TODO: Allow class return types?
      JClassType classReturn = method.getReturnType().isInterface();
      if (classReturn != null) {
        maybeCalculate(classReturn);
        if (noWrapTypes != null) {
          for (JClassType noWrap : noWrapTypes) {
            if (noWrap.isAssignableFrom(classReturn)) {
              builder.setNoWrap(true);
              break;
            }
          }
        }
      }

      // GET, SET, or CALL
      JBeanMethod action = JBeanMethod.which(method);
      builder.setAction(action);
      if (JBeanMethod.CALL.equals(action)) {
        JMethod staticImpl = findStaticImpl(beanType, method);
        if (staticImpl == null && objectMethods.contains(method)) {
          // Don't complain about lack of implementation for Object methods
          continue;
        }
        builder.setStaticImp(staticImpl);
      }

      AutoBeanMethod toAdd = builder.build();

      // Collect referenced enums
      if (toAdd.hasEnumMap()) {
        allEnumConstants.putAll(toAdd.getEnumMap());
      }

      // See if parameterizations will pull in more types
      if (toAdd.isCollection()) {
        maybeCalculate(toAdd.getElementType());
      } else if (toAdd.isMap()) {
        maybeCalculate(toAdd.getKeyType());
        maybeCalculate(toAdd.getValueType());
      }

      toReturn.add(toAdd);
    }
    return toReturn;
  }

  private void die(String message) throws UnableToCompleteException {
    poison(message);
    throw new UnableToCompleteException();
  }

  /**
   * Find <code>Object __intercept(AutoBean&lt;?> bean, Object value);</code> in
   * the category types.
   */
  private JMethod findInterceptor(JClassType beanType) {
    if (categoryTypes == null) {
      return null;
    }
    for (JClassType category : categoryTypes) {
      for (JMethod method : category.getOverloads("__intercept")) {
        // Ignore non-static, non-public methods
        // TODO: Implement visibleFrom() to allow package-protected categories
        if (!method.isStatic() || !method.isPublic()) {
          continue;
        }

        JParameter[] params = method.getParameters();
        if (params.length != 2) {
          continue;
        }
        if (!methodAcceptsAutoBeanAsFirstParam(beanType, method)) {
          continue;
        }
        JClassType value = params[1].getType().isClassOrInterface();
        if (value == null) {
          continue;
        }
        if (!oracle.getJavaLangObject().isAssignableTo(value)) {
          continue;
        }
        return method;
      }
    }
    return null;
  }

  /**
   * Search the category types for a static implementation of an interface
   * method. Given the interface method declaration:
   * 
   * <pre>
   * Foo bar(Baz baz);
   * </pre>
   * 
   * this will search the types in {@link #categoryTypes} for the following
   * method:
   * 
   * <pre>
   * public static Foo bar(AutoBean&lt;Intf> bean, Baz baz) {}
   * </pre>
   */
  private JMethod findStaticImpl(JClassType beanType, JMethod method) {
    if (categoryTypes == null) {
      return null;
    }

    for (JClassType category : categoryTypes) {
      // One extra argument for the AutoBean
      JParameter[] methodParams = method.getParameters();
      int requiredArgs = methodParams.length + 1;
      overload : for (JMethod overload : category.getOverloads(method.getName())) {
        if (!overload.isStatic() || !overload.isPublic()) {
          // Ignore non-static, non-public methods
          continue;
        }

        JParameter[] overloadParams = overload.getParameters();
        if (overloadParams.length != requiredArgs) {
          continue;
        }

        if (!methodAcceptsAutoBeanAsFirstParam(beanType, overload)) {
          // Ignore if the first parameter is a primitive or not assignable
          continue;
        }

        // Match the rest of the parameters
        for (int i = 1; i < requiredArgs; i++) {
          JType methodType = methodParams[i - 1].getType();
          JType overloadType = overloadParams[i].getType();
          if (methodType.equals(overloadType)) {
            // Match; exact, the usual case
          } else if (methodType.isClassOrInterface() != null
              && overloadType.isClassOrInterface() != null
              && methodType.isClassOrInterface().isAssignableTo(
                  overloadType.isClassOrInterface())) {
            // Match; assignment-compatible
          } else {
            // No match, keep looking
            continue overload;
          }
        }
        return overload;
      }
    }
    return null;
  }

  private AutoBeanType getAutoBeanType(JClassType beanType) {
    beanType = ModelUtils.ensureBaseType(beanType);
    AutoBeanType toReturn = peers.get(beanType);
    if (toReturn == null) {
      AutoBeanType.Builder builder = new AutoBeanType.Builder();
      builder.setOwnerFactory(this);
      builder.setPeerType(beanType);
      builder.setMethods(computeMethods(beanType));
      builder.setInterceptor(findInterceptor(beanType));
      if (noWrapTypes != null) {
        for (JClassType noWrap : noWrapTypes) {
          if (noWrap.isAssignableFrom(beanType)) {
            builder.setNoWrap(true);
            break;
          }
        }
      }
      toReturn = builder.build();
      peers.put(beanType, toReturn);
    }
    return toReturn;
  }

  /**
   * Enqueue a type in {@link #toCalculate} if {@link #peers} does not already
   * contain an entry.
   */
  private void maybeCalculate(JClassType type) {
    if (type.isInterface() == null || ModelUtils.isValueType(oracle, type)) {
      return;
    }
    if (!peers.containsKey(type)) {
      toCalculate.add(type);
    }
  }

  private boolean methodAcceptsAutoBeanAsFirstParam(JClassType beanType,
      JMethod method) {
    JParameter[] params = method.getParameters();
    if (params.length == 0) {
      return false;
    }
    JClassType paramAsClass = params[0].getType().isClassOrInterface();

    // First parameter is a primitive
    if (paramAsClass == null) {
      return false;
    }

    // Check using base types to account for erasure semantics
    JParameterizedType expectedFirst = oracle.getParameterizedType(
        autoBeanInterface,
        new JClassType[] {ModelUtils.ensureBaseType(beanType)});
    return expectedFirst.isAssignableTo(paramAsClass);
  }

  private void poison(String message, Object... args) {
    logger.log(TreeLogger.ERROR, String.format(message, args));
    poisoned = true;
  }

  private void processClassArrayAnnotation(Class<?>[] classes,
      Collection<JClassType> accumulator) {
    for (Class<?> clazz : classes) {
      JClassType category = oracle.findType(clazz.getCanonicalName());
      if (category == null) {
        poison("Could not find @%s type %s in the TypeOracle",
            Category.class.getSimpleName(), clazz.getCanonicalName());
        continue;
      } else if (!category.isPublic()) {
        poison("Category type %s is not public",
            category.getQualifiedSourceName());
        continue;
      } else if (!category.isStatic() && category.isMemberType()) {
        poison("Category type %s must be static",
            category.getQualifiedSourceName());
        continue;
      }
      accumulator.add(category);
    }
  }
}
