/*
 * Copyright 2011 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.apt;

import com.google.gwt.core.shared.GwtIncompatible;
import com.google.web.bindery.requestfactory.vm.impl.Deobfuscator;
import com.google.web.bindery.requestfactory.vm.impl.OperationData;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

/**
 * Visits a RequestFactory to create its associated DeobfuscatorBuilder, a
 * self-configuring subtype of
 * {@link com.google.web.bindery.requestfactory.vm.impl.Deobfuscator.Builder}
 * which provides the ServiceLayer with type- and method-mapping information.
 */
class DeobfuscatorBuilder extends ScannerBase<Void> {
  private TypeElement requestFactoryElement;
  private final StringBuilder sb = new StringBuilder();

  public String toString() {
    return sb.toString();
  }

  /**
   * Examine a method defined within a RequestFactory.
   */
  @Override
  public Void visitExecutable(ExecutableElement x, State state) {
    if (shouldIgnore(x, state)) {
      return null;
    }
    final TypeElement requestContextElement =
        (TypeElement) state.types.asElement(x.getReturnType());
    new ScannerBase<Void>() {

      /**
       * Scan a method within a RequestContext.
       */
      @Override
      public Void visitExecutable(ExecutableElement x, State state) {
        if (shouldIgnore(x, state)) {
          return null;
        }
        String requestContextBinaryName =
            state.elements.getBinaryName(requestContextElement).toString();
        String clientMethodDescriptor = x.asType().accept(new DescriptorBuilder(), state);
        String domainMethodDescriptor = null;
        ExecutableElement domainElement = (ExecutableElement) state.getClientToDomainMap().get(x);
        if (domainElement == null) {
          /*
           * No mapping from the client to domain type, probably because of an
           * unresolved ServiceName annotation. This can be fixed when building
           * the server by running ValidationTool.
           */
          if (state.mustResolveAllAnnotations()) {
            state.poison(x, Messages
                .deobfuscatorMissingContext(requestContextElement.getSimpleName()));
          }
        } else {
          domainMethodDescriptor = domainElement.asType().accept(new DescriptorBuilder(), state);
        }
        String methodName = x.getSimpleName().toString();

        OperationKey key =
            new OperationKey(requestContextBinaryName, methodName, clientMethodDescriptor);
        println("withOperation(new OperationKey(\"%s\"),", key.get());
        println("  new OperationData.Builder()");
        println("  .withClientMethodDescriptor(\"%s\")", clientMethodDescriptor);
        if (domainMethodDescriptor != null) {
          println("  .withDomainMethodDescriptor(\"%s\")", domainMethodDescriptor);
        }
        println("  .withMethodName(\"%s\")", methodName);
        println("  .withRequestContext(\"%s\")", requestContextBinaryName);
        println("  .build());");
        return super.visitExecutable(x, state);
      }

      /**
       * Scan a RequestContext.
       */
      @Override
      public Void visitType(TypeElement x, State state) {
        scanAllInheritedMethods(x, state);
        return null;
      }
    }.scan(requestContextElement, state);
    return null;
  }

  /**
   * Scan a RequestFactory type.
   */
  @Override
  public Void visitType(TypeElement x, State state) {
    requestFactoryElement = x;
    String simpleName = computeSimpleName(x, state);
    String packageName = state.elements.getPackageOf(x).getQualifiedName().toString();

    println("// Automatically Generated -- DO NOT EDIT");
    println("// %s", state.elements.getBinaryName(x));
    println("package %s;", packageName);
    println("import %s;", Arrays.class.getCanonicalName());
    println("import %s;", OperationData.class.getCanonicalName());
    println("import %s;", OperationKey.class.getCanonicalName());
    println("import %s;", GwtIncompatible.class.getCanonicalName());
    println("@%s(\"Server-side only but loaded through naming convention "
        + "so must be in same package as shared %s interface\")",
        GwtIncompatible.class.getSimpleName(), x.getSimpleName());
    println("public final class %s extends %s {", simpleName, Deobfuscator.Builder.class
        .getCanonicalName());
    println("{");
    scanAllInheritedMethods(x, state);
    writeTypeAndTokenMap(state);
    println("}}");

    // Don't write the deobfuscator if something has gone wrong.
    if (state.isPoisoned()) {
      return null;
    }

    try {
      JavaFileObject obj = state.filer.createSourceFile(packageName + "." + simpleName, x);
      Writer w = obj.openWriter();
      w.write(sb.toString());
      w.close();
    } catch (Exception e) {
      StringWriter sw = new StringWriter();
      e.printStackTrace(new PrintWriter(sw));
      state.poison(x, sw.toString());
    }
    return null;
  }

  private String computeSimpleName(TypeElement x, State state) {
    // See constants in Deobfuscator
    String simpleName = state.elements.getBinaryName(x).toString() + "DeobfuscatorBuilder";
    if (state.isClientOnly()) {
      simpleName += "Lite";
    }
    simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1);
    return simpleName;
  }

  private void println(String line, Object... args) {
    sb.append(String.format(line, args)).append("\n");
  }

  /**
   * Write calls to {@code withRawTypeToken} and
   * {@code withClientToDomainMappings}.
   */
  private void writeTypeAndTokenMap(State state) {
    /*
     * A map and its comparator to build up the mapping between domain types and
     * the client type(s) that it is mapped to.
     */
    TypeComparator comparator = new TypeComparator(state);
    Map<TypeElement, SortedSet<TypeElement>> domainToClientMappings =
        new TreeMap<TypeElement, SortedSet<TypeElement>>(comparator);
    // Map accumulated by previous visitors
    Map<Element, Element> clientToDomainMap = state.getClientToDomainMap();
    // Get all types used by the RequestFactory
    Set<TypeElement> referredTypes = ReferredTypesCollector.collect(requestFactoryElement, state);

    for (TypeElement clientType : referredTypes) {
      // Ignare non-proxy types
      if (!state.types.isAssignable(clientType.asType(), state.baseProxyType)) {
        continue;
      }
      String binaryName = state.elements.getBinaryName(clientType).toString();
      // withRawTypeToken("1234ABC", "com.example.FooProxy");
      println("withRawTypeToken(\"%s\", \"%s\");", OperationKey.hash(binaryName), binaryName);

      TypeElement domainType = (TypeElement) clientToDomainMap.get(clientType);
      if (domainType == null) {
        /*
         * Missing proxy mapping, probably due to an unresolved ProxyForName. If
         * we're running as part of a build tool or an IDE, the
         * mustResolveAllAnnotations() call below will return false. The
         * isMappingRequired() check avoid false-positives on proxy supertypes
         * that extend BaseProxy but that don't declare a ProxyFor annotation.
         */
        if (state.mustResolveAllAnnotations() && state.isMappingRequired(domainType)) {
          state.poison(clientType, Messages.deobfuscatorMissingProxy(clientType.getSimpleName()));
        }
        continue;
      }
      // Generic get-and-add code
      SortedSet<TypeElement> clientTypes = domainToClientMappings.get(domainType);
      if (clientTypes == null) {
        clientTypes = new TreeSet<TypeElement>(comparator);
        domainToClientMappings.put(domainType, clientTypes);
      }
      clientTypes.add(clientType);
    }

    for (Map.Entry<TypeElement, SortedSet<TypeElement>> entry : domainToClientMappings.entrySet()) {
      // Arrays.asList("com.example.FooView1Proxy", "com.example.FooView2Proxy")
      StringBuilder list = new StringBuilder("Arrays.asList(");
      boolean needsComma = false;
      for (TypeElement elt : entry.getValue()) {
        if (needsComma) {
          list.append(", ");
        } else {
          needsComma = true;
        }
        list.append('"').append(state.elements.getBinaryName(elt)).append('"');
      }
      list.append(")");

      // withClientToDomainMappings("com.example.Domain", Arrays.asList(...))
      println("withClientToDomainMappings(\"%s\", %s);", state.elements.getBinaryName(entry
          .getKey()), list);
    }
  }
}
