/*
 * 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.ListIterator;
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()) ||
        type.getPeerType().getQualifiedSourceName().equals(ListIterator.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("}-*/;");
    }
  }
}
