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

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.impl.WeakMapping;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
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.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
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.rebind.model.ModelUtils;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.web.bindery.autobean.gwt.client.impl.AbstractAutoBeanFactory;
import com.google.web.bindery.autobean.gwt.client.impl.ClientPropertyContext;
import com.google.web.bindery.autobean.gwt.client.impl.JsniCreatorMap;
import com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanFactoryMethod;
import com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanFactoryModel;
import com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanMethod;
import com.google.web.bindery.autobean.gwt.rebind.model.AutoBeanType;
import com.google.web.bindery.autobean.gwt.rebind.model.JBeanMethod;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanFactory;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;
import com.google.web.bindery.autobean.shared.AutoBeanVisitor;
import com.google.web.bindery.autobean.shared.Splittable;
import com.google.web.bindery.autobean.shared.impl.AbstractAutoBean;
import com.google.web.bindery.autobean.shared.impl.AbstractAutoBean.OneShotContext;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Generates implementations of AutoBeanFactory.
 */
public class AutoBeanFactoryGenerator extends Generator {

  private GeneratorContext context;
  private String simpleSourceName;
  private TreeLogger logger;
  private AutoBeanFactoryModel model;

  @Override
  public String generate(TreeLogger logger, GeneratorContext context, String typeName)
      throws UnableToCompleteException {
    this.context = context;
    this.logger = logger;

    TypeOracle oracle = context.getTypeOracle();
    JClassType toGenerate = oracle.findType(typeName).isInterface();
    if (toGenerate == null) {
      logger.log(TreeLogger.ERROR, typeName + " is not an interface type");
      throw new UnableToCompleteException();
    }

    String packageName = toGenerate.getPackage().getName();
    simpleSourceName = toGenerate.getName().replace('.', '_') + "Impl";
    PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName);
    if (pw == null) {
      return packageName + "." + simpleSourceName;
    }

    model = new AutoBeanFactoryModel(logger, toGenerate);

    ClassSourceFileComposerFactory factory =
        new ClassSourceFileComposerFactory(packageName, simpleSourceName);
    factory.setSuperclass(AbstractAutoBeanFactory.class.getCanonicalName());
    factory.addImplementedInterface(typeName);
    SourceWriter sw = factory.createSourceWriter(context, pw);
    for (AutoBeanType type : model.getAllTypes()) {
      writeAutoBean(type);
    }
    writeDynamicMethods(sw);
    writeEnumSetup(sw);
    writeMethods(sw);
    sw.commit(logger);

    return factory.getCreatedClassName();
  }

  /**
   * Flattens a parameterized type into a simple list of types.
   */
  private void createTypeList(List<JType> accumulator, JType type) {
    accumulator.add(type);
    JParameterizedType hasParams = type.isParameterized();
    if (hasParams != null) {
      for (JClassType arg : hasParams.getTypeArgs()) {
        createTypeList(accumulator, arg);
      }
    }
  }

  private String getBaseMethodDeclaration(JMethod jmethod) {
    // Foo foo, Bar bar, Baz baz
    StringBuilder parameters = new StringBuilder();
    for (JParameter param : jmethod.getParameters()) {
      parameters.append(",").append(ModelUtils.getQualifiedBaseSourceName(param.getType())).append(
          " ").append(param.getName());
    }
    if (parameters.length() > 0) {
      parameters = parameters.deleteCharAt(0);
    }

    StringBuilder throwsDeclaration = new StringBuilder();
    if (jmethod.getThrows().length > 0) {
      for (JType thrown : jmethod.getThrows()) {
        throwsDeclaration.append(". ").append(ModelUtils.getQualifiedBaseSourceName(thrown));
      }
      throwsDeclaration.deleteCharAt(0);
      throwsDeclaration.insert(0, "throws ");
    }
    String returnName = ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType());
    assert !returnName.contains("extends");
    return String.format("%s %s(%s) %s", returnName, jmethod.getName(), parameters,
        throwsDeclaration);
  }

  /**
   * Used by {@link #writeShim} to avoid duplicate declarations of Object
   * methods.
   */
  private boolean isObjectMethodImplementedByShim(JMethod jmethod) {
    String methodName = jmethod.getName();
    JParameter[] parameters = jmethod.getParameters();
    switch (parameters.length) {
      case 0:
        return methodName.equals("hashCode") || methodName.equals("toString");
      case 1:
        return methodName.equals("equals")
            && parameters[0].getType().equals(context.getTypeOracle().getJavaLangObject());
    }
    return false;
  }

  private void writeAutoBean(AutoBeanType type) throws UnableToCompleteException {
    PrintWriter pw = context.tryCreate(logger, type.getPackageNome(), type.getSimpleSourceName());
    if (pw == null) {
      // Previously-created
      return;
    }

    ClassSourceFileComposerFactory factory =
        new ClassSourceFileComposerFactory(type.getPackageNome(), type.getSimpleSourceName());
    factory.setSuperclass(AbstractAutoBean.class.getCanonicalName() + "<"
        + type.getPeerType().getQualifiedSourceName() + ">");
    SourceWriter sw = factory.createSourceWriter(context, pw);

    writeShim(sw, type);

    // Instance initializer code to set the shim's association
    sw.println("{ %s.set(shim, %s.class.getName(), this); }", WeakMapping.class.getCanonicalName(),
        AutoBean.class.getCanonicalName());

    // Only simple wrappers have a default constructor
    if (type.isSimpleBean()) {
      // public FooIntfAutoBean(AutoBeanFactory factory) {}
      sw.println("public %s(%s factory) {super(factory);}", type.getSimpleSourceName(),
          AutoBeanFactory.class.getCanonicalName());
    }

    // Wrapping constructor
    // public FooIntfAutoBean(AutoBeanFactory factory, FooIntfo wrapped) {
    sw.println("public %s(%s factory, %s wrapped) {", type.getSimpleSourceName(),
        AutoBeanFactory.class.getCanonicalName(), type.getPeerType().getQualifiedSourceName());
    sw.indentln("super(wrapped, factory);");
    sw.println("}");

    // public FooIntf as() {return shim;}
    sw.println("public %s as() {return shim;}", type.getPeerType().getQualifiedSourceName());

    // public Class<Intf> getType() {return Intf.class;}
    sw.println("public Class<%1$s> getType() {return %1$s.class;}", ModelUtils.ensureBaseType(
        type.getPeerType()).getQualifiedSourceName());

    if (type.isSimpleBean()) {
      writeCreateSimpleBean(sw, type);
    }
    writeTraversal(sw, type);
    sw.commit(logger);
  }

  /**
   * For interfaces that consist of nothing more than getters and setters,
   * create a map-based implementation that will allow the AutoBean's internal
   * state to be easily consumed.
   */
  private void writeCreateSimpleBean(SourceWriter sw, AutoBeanType type) {
    sw.println("@Override protected %s createSimplePeer() {", type.getPeerType()
        .getQualifiedSourceName());
    sw.indent();
    // return new FooIntf() {
    sw.println("return new %s() {", type.getPeerType().getQualifiedSourceName());
    sw.indent();
    sw.println("private final %s data = %s.this.data;", Splittable.class.getCanonicalName(), type
        .getQualifiedSourceName());
    for (AutoBeanMethod method : type.getMethods()) {
      JMethod jmethod = method.getMethod();
      JType returnType = jmethod.getReturnType();
      sw.println("public %s {", getBaseMethodDeclaration(jmethod));
      sw.indent();
      switch (method.getAction()) {
        case GET: {
          String castType;
          if (returnType.isPrimitive() != null) {
            castType = returnType.isPrimitive().getQualifiedBoxedSourceName();
            // Boolean toReturn = Other.this.getOrReify("foo");
            sw.println("%s toReturn = %s.this.getOrReify(\"%s\");", castType, type
                .getSimpleSourceName(), method.getPropertyName());
            // return toReturn == null ? false : toReturn;
            sw.println("return toReturn == null ? %s : toReturn;", returnType.isPrimitive()
                .getUninitializedFieldExpression());
          } else if (returnType.equals(context.getTypeOracle().findType(
              Splittable.class.getCanonicalName()))) {
            sw.println("return data.isNull(\"%1$s\") ? null : data.get(\"%1$s\");", method
                .getPropertyName());
          } else {
            // return (ReturnType) Outer.this.getOrReify(\"foo\");
            castType = ModelUtils.getQualifiedBaseSourceName(returnType);
            sw.println("return (%s) %s.this.getOrReify(\"%s\");", castType, type
                .getSimpleSourceName(), method.getPropertyName());
          }
        }
          break;
        case SET:
        case SET_BUILDER: {
          JParameter param = jmethod.getParameters()[0];
          // Other.this.setProperty("foo", parameter);
          sw.println("%s.this.setProperty(\"%s\", %s);", type.getSimpleSourceName(), method
              .getPropertyName(), param.getName());
          if (JBeanMethod.SET_BUILDER.equals(method.getAction())) {
            sw.println("return this;");
          }
          break;
        }
        case CALL:
          // return com.example.Owner.staticMethod(Outer.this, param,
          // param);
          JMethod staticImpl = method.getStaticImpl();
          if (!returnType.equals(JPrimitiveType.VOID)) {
            sw.print("return ");
          }
          sw.print("%s.%s(%s.this", staticImpl.getEnclosingType().getQualifiedSourceName(),
              staticImpl.getName(), type.getSimpleSourceName());
          for (JParameter param : jmethod.getParameters()) {
            sw.print(", %s", param.getName());
          }
          sw.println(");");
          break;
        default:
          throw new RuntimeException();
      }
      sw.outdent();
      sw.println("}");
    }
    sw.outdent();
    sw.println("};");
    sw.outdent();
    sw.println("}");
  }

  /**
   * Write an instance initializer block to populate the creators map.
   */
  private void writeDynamicMethods(SourceWriter sw) {
    List<JClassType> privatePeers = new ArrayList<JClassType>();
    sw.println("@Override protected void initializeCreatorMap(%s map) {", JsniCreatorMap.class
        .getCanonicalName());
    sw.indent();
    for (AutoBeanType type : model.getAllTypes()) {
      if (type.isNoWrap()) {
        continue;
      }
      String classLiteralAccessor;
      JClassType peer = type.getPeerType();
      String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName();
      if (peer.isPublic()) {
        classLiteralAccessor = peerName + ".class";
      } else {
        privatePeers.add(peer);
        classLiteralAccessor = "classLit_" + peerName.replace('.', '_') + "()";
      }
      // map.add(Foo.class, getConstructors_com_foo_Bar());
      sw.println("map.add(%s, getConstructors_%s());", classLiteralAccessor, peerName.replace('.',
          '_'));
    }
    sw.outdent();
    sw.println("}");

    /*
     * Create a native method for each peer type that isn't public since Java
     * class literal references are scoped.
     */
    for (JClassType peer : privatePeers) {
      String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName();
      sw.println("private native Class<?> classLit_%s() /*-{return @%s::class;}-*/;", peerName
          .replace('.', '_'), peerName);
    }

    /*
     * Create a method that returns an array containing references to the
     * constructors.
     */
    String factoryJNIName =
        context.getTypeOracle().findType(AutoBeanFactory.class.getCanonicalName())
            .getJNISignature();
    for (AutoBeanType type : model.getAllTypes()) {
      String peerName = ModelUtils.ensureBaseType(type.getPeerType()).getQualifiedSourceName();
      String peerJNIName = ModelUtils.ensureBaseType(type.getPeerType()).getJNISignature();
      /*-
       * private native JsArray<JSO> getConstructors_com_foo_Bar() {
       *   return [
       *     BarProxyImpl::new(ABFactory),
       *     BarProxyImpl::new(ABFactory, DelegateType)
       *   ];
       * }
       */
      sw.println("private native %s<%s> getConstructors_%s() /*-{", JsArray.class
          .getCanonicalName(), JavaScriptObject.class.getCanonicalName(), peerName
          .replace('.', '_'));
      sw.indent();
      sw.println("return [");
      if (type.isSimpleBean()) {
        sw.indentln("@%s::new(%s),", type.getQualifiedSourceName(), factoryJNIName);
      } else {
        sw.indentln(",");
      }
      sw.indentln("@%s::new(%s%s)", type.getQualifiedSourceName(), factoryJNIName, peerJNIName);
      sw.println("];");
      sw.outdent();
      sw.println("}-*/;");
    }
  }

  private void writeEnumSetup(SourceWriter sw) {
    // Make the deobfuscation model
    Map<String, List<JEnumConstant>> map = new HashMap<String, List<JEnumConstant>>();
    for (Map.Entry<JEnumConstant, String> entry : model.getEnumTokenMap().entrySet()) {
      List<JEnumConstant> list = map.get(entry.getValue());
      if (list == null) {
        list = new ArrayList<JEnumConstant>();
        map.put(entry.getValue(), list);
      }
      list.add(entry.getKey());
    }

    sw.println("@Override protected void initializeEnumMap() {");
    sw.indent();
    for (Map.Entry<JEnumConstant, String> entry : model.getEnumTokenMap().entrySet()) {
      // enumToStringMap.put(Enum.FOO, "FOO");
      sw.println("enumToStringMap.put(%s.%s, \"%s\");", entry.getKey().getEnclosingType()
          .getQualifiedSourceName(), entry.getKey().getName(), entry.getValue());
    }
    for (Map.Entry<String, List<JEnumConstant>> entry : map.entrySet()) {
      String listExpr;
      if (entry.getValue().size() == 1) {
        JEnumConstant e = entry.getValue().get(0);
        // Collections.singletonList(Enum.FOO)
        listExpr =
            String.format("%s.<%s<?>> singletonList(%s.%s)", Collections.class.getCanonicalName(),
                Enum.class.getCanonicalName(), e.getEnclosingType().getQualifiedSourceName(), e
                    .getName());
      } else {
        // Arrays.asList(Enum.FOO, OtherEnum.FOO, ThirdEnum,FOO)
        StringBuilder sb = new StringBuilder();
        boolean needsComma = false;
        sb.append(String.format("%s.<%s<?>> asList(", Arrays.class.getCanonicalName(), Enum.class
            .getCanonicalName()));
        for (JEnumConstant e : entry.getValue()) {
          if (needsComma) {
            sb.append(",");
          }
          needsComma = true;
          sb.append(e.getEnclosingType().getQualifiedSourceName()).append(".").append(e.getName());
        }
        sb.append(")");
        listExpr = sb.toString();
      }
      sw.println("stringsToEnumsMap.put(\"%s\", %s);", entry.getKey(), listExpr);
    }
    sw.outdent();
    sw.println("}");
  }

  private void writeMethods(SourceWriter sw) throws UnableToCompleteException {
    for (AutoBeanFactoryMethod method : model.getMethods()) {
      AutoBeanType autoBeanType = method.getAutoBeanType();
      // public AutoBean<Foo> foo(FooSubtype wrapped) {
      sw.println("public %s %s(%s) {", method.getReturnType().getQualifiedSourceName(), method
          .getName(), method.isWrapper()
          ? (method.getWrappedType().getQualifiedSourceName() + " wrapped") : "");
      if (method.isWrapper()) {
        sw.indent();
        // AutoBean<Foo> toReturn = AutoBeanUtils.getAutoBean(wrapped);
        sw.println("%s toReturn = %s.getAutoBean(wrapped);", method.getReturnType()
            .getParameterizedQualifiedSourceName(), AutoBeanUtils.class.getCanonicalName());
        sw.println("if (toReturn != null) {return toReturn;}");
        // return new FooAutoBean(Factory.this, wrapped);
        sw.println("return new %s(%s.this, wrapped);", autoBeanType.getQualifiedSourceName(),
            simpleSourceName);
        sw.outdent();
      } else {
        // return new FooAutoBean(Factory.this);
        sw.indentln("return new %s(%s.this);", autoBeanType.getQualifiedSourceName(),
            simpleSourceName);
      }
      sw.println("}");
    }
  }

  private void writeReturnWrapper(SourceWriter sw, AutoBeanType type, AutoBeanMethod method)
      throws UnableToCompleteException {
    if (!method.isValueType() && !method.isNoWrap()) {
      JMethod jmethod = method.getMethod();
      JClassType returnClass = jmethod.getReturnType().isClassOrInterface();
      AutoBeanType peer = model.getPeer(returnClass);

      sw.println("if (toReturn != null) {");
      sw.indent();
      sw.println("if (%s.this.isWrapped(toReturn)) {", type.getSimpleSourceName());
      sw.indentln("toReturn = %s.this.getFromWrapper(toReturn);", type.getSimpleSourceName());
      sw.println("} else {");
      sw.indent();
      if (peer != null) {
        // toReturn = new FooAutoBean(getFactory(), toReturn).as();
        sw.println("toReturn = new %s(getFactory(), toReturn).as();", peer.getQualifiedSourceName());
      }
      sw.outdent();
      sw.println("}");

      sw.outdent();
      sw.println("}");
    }
    // Allow return values to be intercepted
    JMethod interceptor = type.getInterceptor();
    if (interceptor != null) {
      // toReturn = FooCategory.__intercept(FooAutoBean.this, toReturn);
      sw.println("toReturn = %s.%s(%s.this, toReturn);", interceptor.getEnclosingType()
          .getQualifiedSourceName(), interceptor.getName(), type.getSimpleSourceName());
    }
  }

  /**
   * Create the shim instance of the AutoBean's peer type that lets us hijack
   * the method calls. Using a shim type, as opposed to making the AutoBean
   * implement the peer type directly, means that there can't be any conflicts
   * between methods in the peer type and methods declared in the AutoBean
   * implementation.
   */
  private void writeShim(SourceWriter sw, AutoBeanType type) throws UnableToCompleteException {
    // private final FooImpl shim = new FooImpl() {
    sw.println("private final %1$s shim = new %1$s() {", type.getPeerType()
        .getQualifiedSourceName());
    sw.indent();
    for (AutoBeanMethod method : type.getMethods()) {
      JMethod jmethod = method.getMethod();
      if (jmethod.isStatic()) {
        continue;
      }
      String methodName = jmethod.getName();
      JParameter[] parameters = jmethod.getParameters();
      if (isObjectMethodImplementedByShim(jmethod)) {
        // Skip any methods declared on Object, since we have special handling
        continue;
      }

      // foo, bar, baz
      StringBuilder arguments = new StringBuilder();
      {
        for (JParameter param : parameters) {
          arguments.append(",").append(param.getName());
        }
        if (arguments.length() > 0) {
          arguments = arguments.deleteCharAt(0);
        }
      }

      sw.println("public %s {", getBaseMethodDeclaration(jmethod));
      sw.indent();

      switch (method.getAction()) {
        case GET:
          /*
           * The getter call will ensure that any non-value return type is
           * definitely wrapped by an AutoBean instance.
           */
          String getValueType = ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType());
          sw.println("%s toReturn = (%s) %s.this.getWrapped().%s();", getValueType, getValueType,
              type.getSimpleSourceName(), methodName);

          // Non-value types might need to be wrapped
          writeReturnWrapper(sw, type, method);
          sw.println("return toReturn;");
          break;
        case SET:
        case SET_BUILDER:
          // getWrapped().setFoo(foo);
          sw.println("%s.this.getWrapped().%s(%s);", type.getSimpleSourceName(), methodName,
              parameters[0].getName());
          // FooAutoBean.this.set("setFoo", foo);
          sw.println("%s.this.set(\"%s\", %s);", type.getSimpleSourceName(), methodName,
              parameters[0].getName());
          if (JBeanMethod.SET_BUILDER.equals(method.getAction())) {
            sw.println("return this;");
          }
          break;
        case CALL:
          // XXX How should freezing and calls work together?
          // sw.println("checkFrozen();");
          if (JPrimitiveType.VOID.equals(jmethod.getReturnType())) {
            // getWrapped().doFoo(params);
            sw.println("%s.this.getWrapped().%s(%s);", type.getSimpleSourceName(), methodName,
                arguments);
            // call("doFoo", null, params);
            sw.println("%s.this.call(\"%s\", null%s %s);", type.getSimpleSourceName(), methodName,
                arguments.length() > 0 ? "," : "", arguments);
          } else {
            // Type toReturn = (Type) getWrapped().doFoo(params);
            String callValueType = ModelUtils.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName();
            sw.println("%s toReturn = (%s) %s.this.getWrapped().%s(%s);", callValueType, callValueType,
                type.getSimpleSourceName(), methodName, arguments);
            // Non-value types might need to be wrapped
            writeReturnWrapper(sw, type, method);
            // call("doFoo", toReturn, params);
            sw.println("%s.this.call(\"%s\", toReturn%s %s);", type.getSimpleSourceName(),
                methodName, arguments.length() > 0 ? "," : "", arguments);
            sw.println("return toReturn;");
          }
          break;
        default:
          throw new RuntimeException();
      }
      sw.outdent();
      sw.println("}");
    }

    // HACK: Iterator#remove was changed to a default method in Java 8,
    // and those are hidden to generators
    if (type.getPeerType().getQualifiedSourceName().equals(Iterator.class.getCanonicalName())) {
      sw.println("@Override public void remove() {");
      sw.indent();
      sw.println("%s.this.getWrapped().remove();", type.getSimpleSourceName());
      sw.println("%s.this.call(\"remove\", null);", type.getSimpleSourceName());
      sw.outdent();
      sw.println("}");
    }

    // Delegate equals(), hashCode(), and toString() to wrapped object
    sw.println("@Override public boolean equals(Object o) {");
    sw.indentln("return this == o || getWrapped().equals(o);");
    sw.println("}");
    sw.println("@Override public int hashCode() {");
    sw.indentln("return getWrapped().hashCode();");
    sw.println("}");
    sw.println("@Override public String toString() {");
    sw.indentln("return getWrapped().toString();");
    sw.println("}");

    // End of shim field declaration and assignment
    sw.outdent();
    sw.println("};");
  }

  /**
   * Generate traversal logic.
   */
  private void writeTraversal(SourceWriter sw, AutoBeanType type) {
    List<AutoBeanMethod> referencedSetters = new ArrayList<AutoBeanMethod>();
    sw.println("@Override protected void traverseProperties(%s visitor, %s ctx) {",
        AutoBeanVisitor.class.getCanonicalName(), OneShotContext.class.getCanonicalName());
    sw.indent();
    sw.println("%s bean;", AbstractAutoBean.class.getCanonicalName());
    sw.println("Object value;");
    sw.println("%s propertyContext;", ClientPropertyContext.class.getCanonicalName());
    // Local variable ref cleans up emitted js
    sw.println("%1$s as = as();", type.getPeerType().getQualifiedSourceName());

    for (AutoBeanMethod method : type.getMethods()) {
      if (!method.getAction().equals(JBeanMethod.GET)) {
        continue;
      }

      AutoBeanMethod setter = null;
      // If it's not a simple bean type, try to find a real setter method
      if (!type.isSimpleBean()) {
        for (AutoBeanMethod maybeSetter : type.getMethods()) {
          boolean isASetter =
              maybeSetter.getAction().equals(JBeanMethod.SET)
                  || maybeSetter.getAction().equals(JBeanMethod.SET_BUILDER);
          if (isASetter && maybeSetter.getPropertyName().equals(method.getPropertyName())) {
            setter = maybeSetter;
            break;
          }
        }
      }

      // The type of property influences the visitation
      String valueExpression =
          String.format("bean = (%1$s) %2$s.getAutoBean(as.%3$s());", AbstractAutoBean.class
              .getCanonicalName(), AutoBeanUtils.class.getCanonicalName(), method.getMethod()
              .getName());
      String visitMethod;
      String visitVariable = "bean";
      if (method.isCollection()) {
        visitMethod = "Collection";
      } else if (method.isMap()) {
        visitMethod = "Map";
      } else if (method.isValueType()) {
        valueExpression = String.format("value = as.%s();", method.getMethod().getName());
        visitMethod = "Value";
        visitVariable = "value";
      } else {
        visitMethod = "Reference";
      }
      sw.println(valueExpression);

      // Map<List<Foo>, Bar> --> Map, List, Foo, Bar
      List<JType> typeList = new ArrayList<JType>();
      createTypeList(typeList, method.getMethod().getReturnType());
      assert typeList.size() > 0;

      /*
       * Make the PropertyContext that lets us call the setter. We allow
       * multiple methods to be bound to the same property (e.g. to allow JSON
       * payloads to be interpreted as different types). The leading underscore
       * allows purely numeric property names, which are valid JSON map keys.
       */
      // propertyContext = new CPContext(.....);
      sw.println("propertyContext = new %s(", ClientPropertyContext.class.getCanonicalName());
      sw.indent();
      // The instance on which the context is nominally operating
      sw.println("as,");
      // Produce a JSNI reference to a setter function to call
      {
        if (setter != null) {
          // Call a method that returns a JSNI reference to the method to call
          // setFooMethodReference(),
          sw.println("%sMethodReference(as),", setter.getMethod().getName());
          referencedSetters.add(setter);
        } else {
          // Create a function that will update the values map
          // CPContext.beanSetter(FooBeanImpl.this, "foo");
          sw.println("%s.beanSetter(%s.this, \"%s\"),", ClientPropertyContext.Setter.class
              .getCanonicalName(), type.getSimpleSourceName(), method.getPropertyName());
        }
      }
      if (typeList.size() == 1) {
        sw.println("%s.class", ModelUtils.ensureBaseType(typeList.get(0)).getQualifiedSourceName());
      } else {
        // Produce the array of parameter types
        sw.print("new Class<?>[] {");
        boolean first = true;
        for (JType lit : typeList) {
          if (first) {
            first = false;
          } else {
            sw.print(", ");
          }
          sw.print("%s.class", ModelUtils.ensureBaseType(lit).getQualifiedSourceName());
        }
        sw.println("},");

        // Produce the array of parameter counts
        sw.print("new int[] {");
        first = true;
        for (JType lit : typeList) {
          if (first) {
            first = false;
          } else {
            sw.print(", ");
          }
          JParameterizedType hasParam = lit.isParameterized();
          if (hasParam == null) {
            sw.print("0");
          } else {
            sw.print(String.valueOf(hasParam.getTypeArgs().length));
          }
        }
        sw.println("}");
      }
      sw.outdent();
      sw.println(");");

      // if (visitor.visitReferenceProperty("foo", value, ctx))
      sw.println("if (visitor.visit%sProperty(\"%s\", %s, propertyContext)) {", visitMethod, method
          .getPropertyName(), visitVariable);
      if (!method.isValueType()) {
        // Cycle-detection in AbstractAutoBean.traverse
        sw.indentln("if (bean != null) { bean.traverse(visitor, ctx); }");
      }
      sw.println("}");
      // visitor.endVisitorReferenceProperty("foo", value, ctx);
      sw.println("visitor.endVisit%sProperty(\"%s\", %s, propertyContext);", visitMethod, method
          .getPropertyName(), visitVariable);
    }
    sw.outdent();
    sw.println("}");

    for (AutoBeanMethod method : referencedSetters) {
      JMethod jmethod = method.getMethod();
      assert jmethod.getParameters().length == 1;

      /*-
       * Setter setFooMethodReference(Object instance) {
       *   return instance.@com.example.Blah::setFoo(Lcom/example/Foo;);
       * }
       */
      sw.println("public static native %s %sMethodReference(Object instance) /*-{",
          ClientPropertyContext.Setter.class.getCanonicalName(), jmethod.getName());
      sw.indentln("return instance.@%s::%s(%s);", jmethod.getEnclosingType()
          .getQualifiedSourceName(), jmethod.getName(), jmethod.getParameters()[0].getType()
          .getJNISignature());
      sw.println("}-*/;");
    }
  }
}
