/*
 * 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.gwt.editor.rebind.model;

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.JField;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.client.CompositeEditor;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.IsEditor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Analyzes an Editor driver declaration.
 */
public class EditorModel {
  private static final EditorData[] EMPTY_EDITOR_DATA = new EditorData[0];

  /**
   * Given type assignable to <code>ComposedEditor&lt;Foo,Bar></code>, return
   * <code>{Foo, Bar}</code>. It is an error to call this method with a type not
   * assignable to {@link ComposedEditor}.
   */
  static JClassType[] calculateCompositeTypes(JClassType editorType) {
    JClassType compositeEditorIntf = editorType.getOracle().findType(
        CompositeEditor.class.getName());
    assert compositeEditorIntf.isAssignableFrom(editorType) : editorType.getQualifiedSourceName()
        + " is not a ComposedEditor";

    for (JClassType supertype : editorType.getFlattenedSupertypeHierarchy()) {
      JParameterizedType parameterized = supertype.isParameterized();
      if (parameterized != null) {
        // Found the Editor<Foo> supertype
        if (compositeEditorIntf.equals(parameterized.getBaseType())) {
          JClassType[] typeArgs = parameterized.getTypeArgs();
          assert typeArgs.length == 3;
          return new JClassType[]{typeArgs[1], typeArgs[2]};
        }
      }
    }
    assert false : "Did not find ComposedEditor parameterization for "
        + editorType.getQualifiedSourceName();
    throw new RuntimeException();
  }

  /**
   * Given type assignable to <code>Editor&lt;Foo></code>, return
   * <code>Foo</code>. It is an error to call this method with a type not
   * assignable to {@link Editor}.
   */
  static JClassType calculateEditedType(TreeLogger logger, JClassType editorType)
      throws UnableToCompleteException {
    JClassType editorIntf = editorType.getOracle().findType(
        Editor.class.getName());
    JClassType parameterization[] = ModelUtils.findParameterizationOf(
        editorIntf, editorType);
    if (parameterization != null) {
      return parameterization[0];
    }
    logger.log(TreeLogger.ERROR,
        noEditorParameterizationMessage(editorIntf, editorType));
    throw new UnableToCompleteException();
  }

  /**
   * Given type assignable to <code>IsEditor&lt;Foo, FooEditor></code>, return
   * <code>FooEditor</code>. It is an error to call this method with a type not
   * assignable to {@link IsEditor}.
   */
  static JClassType calculateIsEditedType(TreeLogger logger,
      JClassType editorType) throws UnableToCompleteException {
    JClassType editorIntf = editorType.getOracle().findType(
        IsEditor.class.getName());
    JClassType[] parameterization = ModelUtils.findParameterizationOf(
        editorIntf, editorType);
    if (parameterization != null) {
      return parameterization[0];
    }
    logger.log(TreeLogger.ERROR,
        noEditorParameterizationMessage(editorIntf, editorType));
    throw new UnableToCompleteException();
  }

  static String cycleErrorMessage(JType editorType, String originalPath,
      String errorPath) {
    return String.format(
        "Cycle detected in editor graph. Editor type %s at path %s can"
            + " be reached again at path %s",
        editorType.getQualifiedSourceName(), originalPath, errorPath);
  }

  static String foundPrimitiveMessage(JType type, String getterExpression,
      String path) {
    return String.format("Found unexpected type %s while evauating path"
        + " \"%s\" using getter expression \"%s\"",
        type.getQualifiedSourceName(), path, getterExpression);
  }

  static String mustExtendMessage(JType driverType) {
    return String.format(
        "You must declare an interface that extends the %s type",
        driverType.getSimpleSourceName());
  }

  static String noEditorParameterizationMessage(JClassType editorIntf,
      JClassType type) {
    return String.format("The type %s is assignable to the raw %s type, but"
        + " a type parameterization is required.",
        type.getParameterizedQualifiedSourceName(), editorIntf.getName());
  }

  static String noGetterMessage(String propertyName, JType proxyType) {
    return String.format(
        "Could not find a getter for path %s in proxy type %s", propertyName,
        proxyType.getQualifiedSourceName());
  }

  static String poisonedMessage() {
    return "Unable to create Editor model due to previous errors";
  }

  static String tooManyInterfacesMessage(JType intf) {
    return String.format("The type %s extends more than one interface",
        intf.getQualifiedSourceName());
  }

  static String unexpectedInputTypeMessage(JType driverType, JType intf) {
    return String.format("Unexpected input type: %s is not assignable from %s",
        driverType.getQualifiedSourceName(), intf.getQualifiedSourceName());
  }

  private final JGenericType compositeEditorIntf;

  /**
   * The structural model.
   */
  private final EditorData[] editorData;
  /**
   * A reference to {@link Editor}.
   */
  private final JGenericType editorIntf;

  private final JClassType editorType;

  private final EditorData editorSoFar;

  /**
   * A reference to {@link IsEditor}.
   */
  private final JGenericType isEditorIntf;

  private final TreeLogger logger;

  private final EditorModel parentModel;

  private boolean poisoned;

  private final JClassType proxyType;

  /**
   * Type-specific data.
   */
  private final Map<JClassType, List<EditorData>> typeData;

  /**
   * Constructor to use when starting with an EditorDriver interface.
   */
  public EditorModel(TreeLogger logger, JClassType intf, JClassType driverType)
      throws UnableToCompleteException {
    assert logger != null : "logger was null";
    assert intf != null : "intf was null";
    assert driverType != null : "driver was null";

    editorSoFar = null;
    this.logger = logger.branch(TreeLogger.DEBUG, "Creating Editor model for "
        + intf.getQualifiedSourceName());
    parentModel = null;
    typeData = new HashMap<JClassType, List<EditorData>>();

    if (!driverType.isAssignableFrom(intf)) {
      die(unexpectedInputTypeMessage(driverType, intf));
    } else if (intf.equals(driverType)) {
      die(mustExtendMessage(driverType));
    }

    TypeOracle oracle = intf.getOracle();
    editorIntf = oracle.findType(Editor.class.getName()).isGenericType();
    assert editorIntf != null : "No Editor type";
    isEditorIntf = oracle.findType(IsEditor.class.getName()).isGenericType();
    assert isEditorIntf != null : "No IsEditor type";
    compositeEditorIntf = oracle.findType(CompositeEditor.class.getName()).isGenericType();
    assert compositeEditorIntf != null : "No CompositeEditor type";

    JClassType[] interfaces = intf.getImplementedInterfaces();
    if (interfaces.length != 1) {
      die(tooManyInterfacesMessage(intf));
    }

    JClassType[] parameters = ModelUtils.findParameterizationOf(driverType,
        intf);
    assert parameters.length == 2 : "Unexpected number of type parameters";
    proxyType = parameters[0];
    editorType = parameters[1];
    editorData = calculateEditorData();

    if (poisoned) {
      die(poisonedMessage());
    }
  }

  private EditorModel(EditorModel parent, JClassType editorType,
      EditorData subEditor, JClassType proxyType)
      throws UnableToCompleteException {
    logger = parent.logger.branch(TreeLogger.DEBUG, "Descending into "
        + subEditor.getPath());
    this.compositeEditorIntf = parent.compositeEditorIntf;
    this.editorIntf = parent.editorIntf;
    this.editorType = editorType;
    this.editorSoFar = subEditor;
    this.isEditorIntf = parent.isEditorIntf;
    this.parentModel = parent;
    this.proxyType = proxyType;
    this.typeData = parent.typeData;

    editorData = calculateEditorData();
  }

  public EditorData[] getEditorData() {
    return editorData;
  }

  /**
   * Guaranteed to never return null.
   */
  public EditorData[] getEditorData(JClassType editor) {
    List<EditorData> toReturn = typeData.get(editor);
    if (toReturn == null) {
      return EMPTY_EDITOR_DATA;
    }
    return toReturn.toArray(new EditorData[toReturn.size()]);
  }

  public JClassType getEditorType() {
    return editorType;
  }

  public JClassType getProxyType() {
    return proxyType;
  }

  public EditorData getRootData() throws UnableToCompleteException {
    TreeLogger rootLogger = logger.branch(TreeLogger.DEBUG,
        "Calculating root data for "
            + getEditorType().getParameterizedQualifiedSourceName());
    return new EditorData.Builder(rootLogger).access(
        EditorAccess.root(getEditorType())).build();
  }

  private void accumulateEditorData(List<EditorData> data,
      List<EditorData> flatData, List<EditorData> allData)
      throws UnableToCompleteException {
    flatData.addAll(data);
    allData.addAll(data);
    for (EditorData d : data) {
      descendIntoSubEditor(allData, d);
    }
  }

  /**
   * Create the EditorData objects for the {@link #editorData} type.
   * Essentially, the point of this method is to calculate the paths of all
   * Editor types referenced by {@link #editorType}.
   */
  private EditorData[] calculateEditorData() throws UnableToCompleteException {
    List<EditorData> flatData = new ArrayList<EditorData>();
    List<EditorData> toReturn = new ArrayList<EditorData>();

    for (JClassType type : editorType.getFlattenedSupertypeHierarchy()) {
      for (JField field : type.getFields()) {
        if (field.isPrivate() || field.isStatic()
            || field.getAnnotation(Editor.Ignore.class) != null) {
          continue;
        }
        JType fieldClassType = field.getType();
        if (shouldExamine(fieldClassType)) {
          List<EditorData> data = createEditorData(EditorAccess.via(field));
          accumulateEditorData(data, flatData, toReturn);
        }
      }
      for (JMethod method : type.getMethods()) {
        if (method.isPrivate() || method.isStatic()
            || method.getAnnotation(Editor.Ignore.class) != null) {
          continue;
        }
        JType methodReturnType = method.getReturnType();
        if (shouldExamine(methodReturnType)
            && method.getParameters().length == 0) {
          EditorAccess access = EditorAccess.via(method);
          if (access.getPath().equals("as")
              && isEditorIntf.isAssignableFrom(editorType)) {
            // Ignore IsEditor.asEditor()
            continue;
          } else if (access.getPath().equals("createEditorForTraversal")
              && compositeEditorIntf.isAssignableFrom(editorType)) {
            // Ignore CompositeEditor.createEditorForTraversal();
            continue;
          }
          List<EditorData> data = createEditorData(access);
          accumulateEditorData(data, flatData, toReturn);
        }
      }
      type = type.getSuperclass();
    }

    if (compositeEditorIntf.isAssignableFrom(editorType)) {
      JClassType subEditorType = calculateCompositeTypes(editorType)[1];
      EditorAccess access = EditorAccess.root(subEditorType);
      EditorData subEditor = new EditorData.Builder(logger).access(access).parent(
          editorSoFar).build();
      List<EditorData> accumulator = new ArrayList<EditorData>();
      descendIntoSubEditor(accumulator, subEditor);

      /*
       * It's necessary to generate a sub-Model here so that any Editor types
       * reachable only through the composite type will be added to the types
       * map. The path data isn't actually useful, since we rely on
       * CompositeEditor.getPathElement() at runtime.
       */
      EditorModel subModel = new EditorModel(this, subEditor.getEditorType(),
          subEditor, subEditor.getEditedType());
      poisoned |= subModel.poisoned;
    }

    if (!typeData.containsKey(editorType)) {
      typeData.put(editorType, flatData);
    }

    return toReturn.toArray(new EditorData[toReturn.size()]);
  }

  private String camelCase(String prefix, String name) {
    StringBuilder sb = new StringBuilder();
    sb.append(prefix).append(Character.toUpperCase(name.charAt(0))).append(
        name, 1, name.length());
    return sb.toString();
  }

  private List<EditorData> createEditorData(EditorAccess access)
      throws UnableToCompleteException {
    TreeLogger subLogger = logger.branch(TreeLogger.DEBUG, "Examining "
        + access.toString());

    List<EditorData> toReturn = new ArrayList<EditorData>();

    // Are we looking at a view that implements IsEditor?
    if (access.isEditor()) {
      EditorAccess subAccess = EditorAccess.via(access,
          calculateIsEditedType(subLogger, access.getEditorType()));
      toReturn = createEditorData(subAccess);

      // If an object only implements IsEditor, return now
      if (!editorIntf.isAssignableFrom(access.getEditorType())) {
        return toReturn;
      }
    }

    // Determine the Foo in Editor<Foo>
    JClassType expectedToEdit = calculateEditedType(subLogger,
        access.getEditorType());

    EditorData.Builder builder = new EditorData.Builder(subLogger);
    builder.access(access);
    builder.parent(editorSoFar);

    // Find the bean methods on the proxy interface
    findBeanPropertyMethods(access.getPath(), expectedToEdit, builder);

    toReturn.add(builder.build());
    return toReturn;
  }

  /**
   * @param accumulator
   * @param data
   * @throws UnableToCompleteException
   */
  private void descendIntoSubEditor(List<EditorData> accumulator,
      EditorData data) throws UnableToCompleteException {
    EditorModel superModel = parentModel;
    while (superModel != null) {
      if (superModel.editorType.isAssignableFrom(data.getEditorType())
          || data.getEditorType().isAssignableFrom(superModel.editorType)) {
        poison(cycleErrorMessage(data.getEditorType(), superModel.getPath(),
            data.getPath()));
        return;
      }
      superModel = superModel.parentModel;
    }

    if (data.isDelegateRequired()) {
      EditorModel subModel = new EditorModel(this, data.getEditorType(), data,
          calculateEditedType(logger, data.getEditorType()));
      accumulator.addAll(accumulator.indexOf(data) + 1,
          Arrays.asList(subModel.getEditorData()));
      poisoned |= subModel.poisoned;
    }
  }

  private void die(String message) throws UnableToCompleteException {
    logger.log(TreeLogger.ERROR, message);
    throw new UnableToCompleteException();
  }

  /**
   * Traverses a path to create expressions to access the getter and setter.
   * <p>
   * This method returns a three-element string array containing the
   * interstitial getter expression specified by the path, the name of the
   * getter method, and the name of the setter method. For example, the input
   * <code>foo.bar.baz</code> might return
   * <code>{ ".getFoo().getBar()", "getBaz", "setBaz" }</code>.
   */
  private void findBeanPropertyMethods(String path, JClassType propertyType,
      EditorData.Builder builder) {
    StringBuilder interstitialGetters = new StringBuilder();
    StringBuilder interstitialGuard = new StringBuilder("true");
    String[] parts = path.split(Pattern.quote("."));
    String setterName = null;

    JClassType lookingAt = proxyType;
    part : for (int i = 0, j = parts.length; i < j; i++) {
      if (parts[i].length() == 0) {
        continue;
      }
      String getterName = camelCase("get", parts[i]);

      for (JClassType search : lookingAt.getFlattenedSupertypeHierarchy()) {
        // If looking at the last element of the path, also look for a setter
        if (i == j - 1 && setterName == null) {
          for (JMethod maybeSetter : search.getOverloads(camelCase("set",
              parts[i]))) {
            if (maybeSetter.getReturnType().equals(JPrimitiveType.VOID)
                && maybeSetter.getParameters().length == 1
                && maybeSetter.getParameters()[0].getType().isClassOrInterface() != null
                && maybeSetter.getParameters()[0].getType().isClassOrInterface().isAssignableFrom(
                    propertyType)) {
              setterName = maybeSetter.getName();
              break;
            }
          }
        }

        JMethod getter = search.findMethod(getterName, new JType[0]);
        if (getter != null) {
          JType returnType = getter.getReturnType();
          lookingAt = returnType.isClassOrInterface();
          if (lookingAt == null) {
            poison(foundPrimitiveMessage(returnType,
                interstitialGetters.toString(), path));
            return;
          }
          interstitialGetters.append(".").append(getterName).append("()");
          interstitialGuard.append(" && %1$s").append(interstitialGetters).append(
              " != null");
          builder.propertyOwnerType(search);
          continue part;
        }
      }
      poison(noGetterMessage(path, proxyType));
      return;
    }

    int idx = interstitialGetters.lastIndexOf(".");
    builder.beanOwnerExpression(idx <= 0 ? "" : interstitialGetters.substring(
        0, idx));
    if (parts.length > 1) {
      // Strip after last && since null is a valid value
      interstitialGuard.delete(interstitialGuard.lastIndexOf(" &&"),
          interstitialGuard.length());
      builder.beanOwnerGuard(interstitialGuard.substring(8));
    }
    if (interstitialGetters.length() > 0) {
      builder.getterExpression("."
          + interstitialGetters.substring(idx + 1,
              interstitialGetters.length() - 2) + "()");
    } else {
      builder.getterExpression("");
    }
    builder.setterName(setterName);
  }

  private String getPath() {
    if (editorSoFar != null) {
      return editorSoFar.getPath();
    } else {
      return "<Root Object>";
    }
  }

  /**
   * Record an error that is not immediately fatal.
   */
  private void poison(String message) {
    logger.log(TreeLogger.ERROR, message);
    poisoned = true;
  }

  /**
   * Returns <code>true</code> if the given type participates in Editor
   * hierarchies.
   */
  private boolean shouldExamine(JType type) {
    JClassType classType = type.isClassOrInterface();
    if (classType == null) {
      return false;
    }
    return editorIntf.isAssignableFrom(classType)
        || isEditorIntf.isAssignableFrom(classType);
  }
}
