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

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.AutoBean.PropertyName;
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.client.GWT;
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.JEnumType;
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.JTypeParameter;
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.requestfactory.gwt.client.impl.AbstractClientRequestFactory;
import com.google.web.bindery.requestfactory.gwt.rebind.model.AcceptsModelVisitor;
import com.google.web.bindery.requestfactory.gwt.rebind.model.ContextMethod;
import com.google.web.bindery.requestfactory.gwt.rebind.model.EntityProxyModel;
import com.google.web.bindery.requestfactory.gwt.rebind.model.ModelVisitor;
import com.google.web.bindery.requestfactory.gwt.rebind.model.RequestFactoryModel;
import com.google.web.bindery.requestfactory.gwt.rebind.model.RequestMethod;
import com.google.web.bindery.requestfactory.gwt.rebind.model.EntityProxyModel.Type;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.JsonRpcContent;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequest;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequestFactory;
import com.google.web.bindery.requestfactory.shared.impl.BaseProxyCategory;
import com.google.web.bindery.requestfactory.shared.impl.EntityProxyCategory;
import com.google.web.bindery.requestfactory.shared.impl.RequestData;
import com.google.web.bindery.requestfactory.shared.impl.ValueProxyCategory;
import com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.Dialect;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * Generates implementations of
 * {@link com.google.web.bindery.requestfactory.shared.RequestFactory RequestFactory}
 * and its nested interfaces.
 */
public class RequestFactoryGenerator extends Generator {

  /**
   * Visits all types reachable from a RequestContext.
   */
  private static class AllReachableTypesVisitor extends
      RequestMethodTypesVisitor {
    private final RequestFactoryModel model;

    public AllReachableTypesVisitor(RequestFactoryModel model) {
      this.model = model;
    }

    @Override
    void examineTypeOnce(JClassType type) {
      // Need this to handle List<Foo>, Map<Foo>
      JParameterizedType parameterized = type.isParameterized();
      if (parameterized != null) {
        for (JClassType arg : parameterized.getTypeArgs()) {
          maybeVisit(arg);
        }
      }
      JClassType base = ModelUtils.ensureBaseType(type);
      EntityProxyModel peer = model.getPeer(base);
      if (peer == null) {
        return;
      }
      peer.accept(this);
    }
  }

  /**
   * Visits all types immediately referenced by methods defined in a
   * RequestContext.
   */
  private abstract static class RequestMethodTypesVisitor extends ModelVisitor {
    private final Set<JClassType> seen = new HashSet<JClassType>();

    @Override
    public void endVisit(RequestMethod x) {
      // Request<Foo> -> Foo
      maybeVisit(x.getDataType());
      // InstanceRequest<Proxy, Foo> -> Proxy
      if (x.getInstanceType() != null) {
        x.getInstanceType().accept(this);
      }
      // Request<Void> doSomething(Foo foo, Bar bar) -> Foo, Bar
      for (JType param : x.getDeclarationMethod().getParameterTypes()) {
        maybeVisit(param.isClassOrInterface());
      }
      // setFoo(Foo foo) -> Foo
      for (JMethod method : x.getExtraSetters()) {
        maybeVisit(method.getParameterTypes()[0].isClassOrInterface());
      }
    }

    abstract void examineTypeOnce(JClassType type);

    void maybeVisit(JClassType type) {
      if (type == null) {
        return;
      } else if (!seen.add(type)) {
        // Short-circuit to prevent type-loops
        return;
      }
      examineTypeOnce(type);
    }
  }

  private GeneratorContext context;
  private TreeLogger logger;
  private RequestFactoryModel 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();
    String simpleSourceName = toGenerate.getName().replace('.', '_') + "Impl";
    PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName);
    if (pw == null) {
      return packageName + "." + simpleSourceName;
    }

    model = new RequestFactoryModel(logger, toGenerate);

    ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
        packageName, simpleSourceName);
    factory.setSuperclass(AbstractClientRequestFactory.class.getCanonicalName());
    factory.addImplementedInterface(typeName);
    SourceWriter sw = factory.createSourceWriter(context, pw);
    writeAutoBeanFactory(sw, model.getAllProxyModels(), findExtraEnums(model));
    writeContextMethods(sw);
    writeContextImplementations();
    writeTypeMap(sw);
    sw.commit(logger);

    return factory.getCreatedClassName();
  }

  /**
   * Find enums that needed to be added to the EnumMap that are not referenced
   * by any of the proxies. This is necessary because the RequestFactory depends
   * on the AutoBeanCodex to serialize enum values, which in turn depends on the
   * AutoBeanFactory's enum map. That enum map only contains enum types
   * reachable from the AutoBean interfaces, which could lead to method
   * parameters being un-encodable.
   */
  private Set<JEnumType> findExtraEnums(AcceptsModelVisitor method) {
    final Set<JEnumType> toReturn = new LinkedHashSet<JEnumType>();
    final Set<JEnumType> referenced = new HashSet<JEnumType>();

    // Called from the adder visitor below on each EntityProxy seen
    final ModelVisitor remover = new AllReachableTypesVisitor(model) {
      @Override
      void examineTypeOnce(JClassType type) {
        JEnumType asEnum = type.isEnum();
        if (asEnum != null) {
          referenced.add(asEnum);
        }
        super.examineTypeOnce(type);
      }
    };

    // Add enums used by RequestMethods
    method.accept(new RequestMethodTypesVisitor() {
      @Override
      public boolean visit(EntityProxyModel x) {
        x.accept(remover);
        return false;
      }

      @Override
      void examineTypeOnce(JClassType type) {
        JEnumType asEnum = type.isEnum();
        if (asEnum != null) {
          toReturn.add(asEnum);
        }
      }
    });
    toReturn.removeAll(referenced);
    if (toReturn.isEmpty()) {
      return Collections.emptySet();
    }
    return Collections.unmodifiableSet(toReturn);
  }

  /**
   * Find all EntityProxyModels reachable from a given ContextMethod.
   */
  private Set<EntityProxyModel> findReferencedEntities(ContextMethod method) {
    final Set<EntityProxyModel> models = new LinkedHashSet<EntityProxyModel>();
    method.accept(new AllReachableTypesVisitor(model) {
      @Override
      public void endVisit(EntityProxyModel x) {
        models.add(x);
      }
    });
    return models;
  }

  private void writeAutoBeanFactory(SourceWriter sw,
      Collection<EntityProxyModel> models, Collection<JEnumType> extraEnums) {
    if (!extraEnums.isEmpty()) {
      StringBuilder extraClasses = new StringBuilder();
      for (JEnumType enumType : extraEnums) {
        if (extraClasses.length() > 0) {
          extraClasses.append(",");
        }
        extraClasses.append(enumType.getQualifiedSourceName()).append(".class");
      }
      sw.println("@%s({%s})", ExtraEnums.class.getCanonicalName(), extraClasses);
    }
    // Map in static implementations of EntityProxy methods
    sw.println("@%s({%s.class, %s.class, %s.class})",
        Category.class.getCanonicalName(),
        EntityProxyCategory.class.getCanonicalName(),
        ValueProxyCategory.class.getCanonicalName(),
        BaseProxyCategory.class.getCanonicalName());
    // Don't wrap our id type, because it makes code grungy
    sw.println("@%s(%s.class)", NoWrap.class.getCanonicalName(),
        EntityProxyId.class.getCanonicalName());
    sw.println("interface Factory extends %s {",
        AutoBeanFactory.class.getCanonicalName());
    sw.indent();

    for (EntityProxyModel proxy : models) {
      // AutoBean<FooProxy> com_google_FooProxy();
      sw.println("%s<%s> %s();", AutoBean.class.getCanonicalName(),
          proxy.getQualifiedSourceName(),
          proxy.getQualifiedSourceName().replace('.', '_'));
    }
    sw.outdent();
    sw.println("}");

    // public static final Factory FACTORY = GWT.create(Factory.class);
    sw.println("public static Factory FACTORY;", GWT.class.getCanonicalName());

    // Write public accessor
    sw.println("@Override public Factory getAutoBeanFactory() {");
    sw.indent();
    sw.println("if (FACTORY == null) {");
    sw.indentln("FACTORY = %s.create(Factory.class);",
        GWT.class.getCanonicalName());
    sw.println("}");
    sw.println("return FACTORY;");
    sw.outdent();
    sw.println("}");
  }

  private void writeContextImplementations() {
    for (ContextMethod method : model.getMethods()) {
      PrintWriter pw = context.tryCreate(logger, method.getPackageName(),
          method.getSimpleSourceName());
      if (pw == null) {
        // Already generated
        continue;
      }

      ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(
          method.getPackageName(), method.getSimpleSourceName());
      factory.setSuperclass(AbstractRequestContext.class.getCanonicalName());
      factory.addImplementedInterface(method.getImplementedInterfaceQualifiedSourceName());
      SourceWriter sw = factory.createSourceWriter(context, pw);

      // Constructor that accepts the parent RequestFactory
      sw.println(
          "public %s(%s requestFactory) {super(requestFactory, %s.%s);}",
          method.getSimpleSourceName(),
          AbstractRequestFactory.class.getCanonicalName(),
          Dialect.class.getCanonicalName(), method.getDialect().name());

      Set<EntityProxyModel> models = findReferencedEntities(method);
      Set<JEnumType> extraEnumTypes = findExtraEnums(method);
      writeAutoBeanFactory(sw, models, extraEnumTypes);

      // Write each Request method
      for (RequestMethod request : method.getRequestMethods()) {
        JMethod jmethod = request.getDeclarationMethod();
        String operation = request.getOperation();

        // foo, bar, baz
        StringBuilder parameterArray = new StringBuilder();
        // final Foo foo, final Bar bar, final Baz baz
        StringBuilder parameterDeclaration = new StringBuilder();
        // <P extends Blah>
        StringBuilder typeParameterDeclaration = new StringBuilder();

        if (request.isInstance()) {
          // Leave a spot for the using() method to fill in later
          parameterArray.append(",null");
        }
        for (JTypeParameter param : jmethod.getTypeParameters()) {
          typeParameterDeclaration.append(",").append(
              param.getQualifiedSourceName());
        }
        for (JParameter param : jmethod.getParameters()) {
          parameterArray.append(",").append(param.getName());
          parameterDeclaration.append(",final ").append(
              param.getType().getParameterizedQualifiedSourceName()).append(" ").append(
              param.getName());
        }
        if (parameterArray.length() > 0) {
          parameterArray.deleteCharAt(0);
        }
        if (parameterDeclaration.length() > 0) {
          parameterDeclaration.deleteCharAt(0);
        }
        if (typeParameterDeclaration.length() > 0) {
          typeParameterDeclaration.deleteCharAt(0).insert(0, "<").append(">");
        }

        // public Request<Foo> doFoo(final Foo foo) {
        sw.println("public %s %s %s(%s) {", typeParameterDeclaration,
            jmethod.getReturnType().getParameterizedQualifiedSourceName(),
            jmethod.getName(), parameterDeclaration);
        sw.indent();
        // The implements clause covers InstanceRequest
        // class X extends AbstractRequest<Return> implements Request<Return> {
        sw.println("class X extends %s<%s> implements %s {",
            AbstractRequest.class.getCanonicalName(),
            request.getDataType().getParameterizedQualifiedSourceName(),
            jmethod.getReturnType().getParameterizedQualifiedSourceName());
        sw.indent();

        // public X() { super(FooRequestContext.this); }
        sw.println("public X() { super(%s.this);}",
            method.getSimpleSourceName());

        // This could also be gotten rid of by having only Request /
        // InstanceRequest
        sw.println("@Override public X with(String... paths) {super.with(paths); return this;}");

        // makeRequestData()
        sw.println("@Override protected %s makeRequestData() {",
            RequestData.class.getCanonicalName());
        // return new RequestData("Foo::bar", {parameters}, propertyRefs,
        // List.class, FooProxy.class);
        String elementType = request.isCollectionType()
            ? request.getCollectionElementType().getQualifiedSourceName()
                + ".class" : "null";
        String returnTypeBaseQualifiedName = ModelUtils.ensureBaseType(
            request.getDataType()).getQualifiedSourceName();
        sw.indentln(
            "return new %s(\"%s\", new Object[] {%s}, propertyRefs, %s.class, %s);",
            RequestData.class.getCanonicalName(), operation, parameterArray,
            returnTypeBaseQualifiedName, elementType);
        sw.println("}");

        /*
         * Only support extra properties in JSON-RPC payloads. Could add this to
         * standard requests to provide out-of-band data.
         */
        if (method.getDialect().equals(Dialect.JSON_RPC)) {
          for (JMethod setter : request.getExtraSetters()) {
            PropertyName propertyNameAnnotation = setter.getAnnotation(PropertyName.class);
            String propertyName = propertyNameAnnotation == null
                ? JBeanMethod.SET.inferName(setter)
                : propertyNameAnnotation.value();
            String maybeReturn = JBeanMethod.SET_BUILDER.matches(setter)
                ? "return this;" : "";
            sw.println(
                "%s { getRequestData().setNamedParameter(\"%s\", %s); %s}",
                setter.getReadableDeclaration(false, false, false, false, true),
                propertyName, setter.getParameters()[0].getName(), maybeReturn);
          }
        }

        // end class X{}
        sw.outdent();
        sw.println("}");

        // Instantiate, enqueue, and return
        sw.println("X x = new X();");

        if (request.getApiVersion() != null) {
          sw.println("x.getRequestData().setApiVersion(\"%s\");",
              Generator.escape(request.getApiVersion()));
        }

        // JSON-RPC payloads send their parameters in a by-name fashion
        if (method.getDialect().equals(Dialect.JSON_RPC)) {
          for (JParameter param : jmethod.getParameters()) {
            PropertyName annotation = param.getAnnotation(PropertyName.class);
            String propertyName = annotation == null ? param.getName()
                : annotation.value();
            boolean isContent = param.isAnnotationPresent(JsonRpcContent.class);
            if (isContent) {
              sw.println("x.getRequestData().setRequestContent(%s);",
                  param.getName());
            } else {
              sw.println("x.getRequestData().setNamedParameter(\"%s\", %s);",
                  propertyName, param.getName());
            }
          }
        }

        // See comment in AbstractRequest.using(EntityProxy)
        if (!request.isInstance()) {
          sw.println("addInvocation(x);");
        }
        sw.println("return x;");
        sw.outdent();
        sw.println("}");
      }

      sw.commit(logger);
    }
  }

  private void writeContextMethods(SourceWriter sw) {
    for (ContextMethod method : model.getMethods()) {
      // public FooService foo() {
      sw.println("public %s %s() {", method.getQualifiedSourceName(),
          method.getMethodName());
      // return new FooServiceImpl(this);
      sw.indentln("return new %s(this);", method.getQualifiedSourceName());
      sw.println("}");
    }
  }

  private void writeTypeMap(SourceWriter sw) {
    sw.println("private static final %1$s<String, Class<?>> tokensToTypes"
        + " = new %1$s<String, Class<?>>();", HashMap.class.getCanonicalName());
    sw.println("private static final %1$s<Class<?>, String> typesToTokens"
        + " = new %1$s<Class<?>, String>();", HashMap.class.getCanonicalName());
    sw.println(
        "private static final %1$s<Class<?>> entityProxyTypes = new %1$s<Class<?>>();",
        HashSet.class.getCanonicalName());
    sw.println(
        "private static final %1$s<Class<?>> valueProxyTypes = new %1$s<Class<?>>();",
        HashSet.class.getCanonicalName());
    sw.println("static {");
    sw.indent();
    for (EntityProxyModel type : model.getAllProxyModels()) {
      // tokensToTypes.put("Foo", Foo.class);
      sw.println("tokensToTypes.put(\"%s\", %s.class);",
          type.getQualifiedBinaryName(), type.getQualifiedSourceName());
      // typesToTokens.put(Foo.class, Foo);
      sw.println("typesToTokens.put(%s.class, \"%s\");",
          type.getQualifiedSourceName(), type.getQualifiedBinaryName());
      // fooProxyTypes.add(MyFooProxy.class);
      sw.println("%s.add(%s.class);", type.getType().equals(Type.ENTITY)
          ? "entityProxyTypes" : "valueProxyTypes",
          type.getQualifiedSourceName());
    }
    sw.outdent();
    sw.println("}");

    // Write instance methods
    sw.println("@Override protected Class getTypeFromToken(String typeToken) {");
    sw.indentln("return tokensToTypes.get(typeToken);");
    sw.println("}");
    sw.println("@Override protected String getTypeToken(Class type) {");
    sw.indentln("return typesToTokens.get(type);");
    sw.println("}");
    sw.println("@Override public boolean isEntityType(Class<?> type) {");
    sw.indentln("return entityProxyTypes.contains(type);");
    sw.println("}");
    sw.println("@Override public boolean isValueType(Class<?> type) {");
    sw.indentln("return valueProxyTypes.contains(type);");
    sw.println("}");
  }
}
