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

import com.google.gwt.autobean.rebind.model.JBeanMethod;
import com.google.gwt.autobean.shared.AutoBean;
import com.google.gwt.autobean.shared.AutoBean.PropertyName;
import com.google.gwt.autobean.shared.AutoBeanFactory;
import com.google.gwt.autobean.shared.AutoBeanFactory.Category;
import com.google.gwt.autobean.shared.AutoBeanFactory.NoWrap;
import com.google.gwt.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.requestfactory.client.impl.AbstractClientRequestFactory;
import com.google.gwt.requestfactory.rebind.model.AcceptsModelVisitor;
import com.google.gwt.requestfactory.rebind.model.ContextMethod;
import com.google.gwt.requestfactory.rebind.model.EntityProxyModel;
import com.google.gwt.requestfactory.rebind.model.EntityProxyModel.Type;
import com.google.gwt.requestfactory.rebind.model.ModelVisitor;
import com.google.gwt.requestfactory.rebind.model.RequestFactoryModel;
import com.google.gwt.requestfactory.rebind.model.RequestMethod;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.JsonRpcContent;
import com.google.gwt.requestfactory.shared.impl.AbstractRequest;
import com.google.gwt.requestfactory.shared.impl.AbstractRequestContext;
import com.google.gwt.requestfactory.shared.impl.AbstractRequestContext.Dialect;
import com.google.gwt.requestfactory.shared.impl.AbstractRequestFactory;
import com.google.gwt.requestfactory.shared.impl.BaseProxyCategory;
import com.google.gwt.requestfactory.shared.impl.EntityProxyCategory;
import com.google.gwt.requestfactory.shared.impl.RequestData;
import com.google.gwt.requestfactory.shared.impl.ValueProxyCategory;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

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.gwt.requestfactory.shared.RequestFactory RequestFactory}
 * and its nested interfaces.
 *
 * <p><span style='color:red'>RequestFactory has moved to
 * <code>com.google.web.bindery.requestfactory</code>.  This package will be
 * removed in a future version of GWT.</span></p>
 */
@Deprecated
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;
    }

    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("}");
  }
}
