/*
 * 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.vm.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Provides access to payload deobfuscation services for server and JVM-based
 * clients. The deobfuscation data is baked into GWT-based clients by the
 * generator.
 */
public class Deobfuscator {
  /**
   * Creates Deobfuscators.
   */
  public static class Builder {
    /**
     * Load a pre-computed Builder from the classpath. The builder
     * implementation is expected to have been generated by the annotation
     * processor as part of the build process.
     * 
     * @see com.google.web.bindery.requestfactory.apt.DeobfuscatorBuilder
     * @see com.google.web.bindery.requestfactory.server.ResolverServiceLayer
     */
    public static Builder load(Class<?> clazz, ClassLoader resolveClassesWith) {
      Throwable ex;
      try {
        Class<?> found;
        try {
          // Used by the server
          found = Class.forName(clazz.getName() + GENERATED_SUFFIX, false, resolveClassesWith);
        } catch (ClassNotFoundException ignored) {
          // Used by JRE-only clients
          found = Class.forName(clazz.getName() + GENERATED_SUFFIX_LITE, false, resolveClassesWith);
        }
        Class<? extends Builder> builderClass = found.asSubclass(Builder.class);
        Builder builder = builderClass.newInstance();
        return builder;
      } catch (ClassNotFoundException e) {
        throw new RuntimeException("The RequestFactory ValidationTool must be run for the "
            + clazz.getCanonicalName() + " RequestFactory type");
      } catch (InstantiationException e) {
        ex = e;
      } catch (IllegalAccessException e) {
        ex = e;
      }
      throw new RuntimeException(ex);
    }

    private Deobfuscator d = new Deobfuscator();

    {
      d.domainToClientType = new HashMap<String, List<String>>();
      d.operationData = new HashMap<OperationKey, OperationData>();
      d.typeTokens = new HashMap<String, String>();
    }

    public Deobfuscator build() {
      Deobfuscator toReturn = d;
      toReturn.domainToClientType = Collections.unmodifiableMap(toReturn.domainToClientType);
      toReturn.operationData = Collections.unmodifiableMap(toReturn.operationData);
      toReturn.referencedTypes =
          Collections.unmodifiableSet(new HashSet<String>(toReturn.typeTokens.values()));
      toReturn.typeTokens = Collections.unmodifiableMap(toReturn.typeTokens);
      d = null;
      return toReturn;
    }

    public Builder merge(Deobfuscator existing) {
      d.domainToClientType.putAll(existing.domainToClientType);
      d.operationData.putAll(existing.operationData);
      // referencedTypes recomputed in build()
      d.typeTokens.putAll(existing.typeTokens);
      return this;
    }

    public Builder withClientToDomainMappings(String domainBinaryName, List<String> value) {
      List<String> clientBinaryNames;
      switch (value.size()) {
        case 0:
          clientBinaryNames = Collections.emptyList();
          break;
        case 1:
          clientBinaryNames = Collections.singletonList(value.get(0));
          break;
        default:
          clientBinaryNames = Collections.unmodifiableList(new ArrayList<String>(value));
      }
      d.domainToClientType.put(domainBinaryName, clientBinaryNames);
      return this;
    }

    public Builder withOperation(OperationKey key, OperationData data) {
      d.operationData.put(key, data);
      return this;
    }

    public Builder withRawTypeToken(String token, String binaryName) {
      d.typeTokens.put(token, binaryName);
      return this;
    }
  }

  private static final String GENERATED_SUFFIX = "DeobfuscatorBuilder";
  private static final String GENERATED_SUFFIX_LITE = GENERATED_SUFFIX + "Lite";

  /**
   * Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
   * FooBProxy).
   */
  private Map<String, List<String>> domainToClientType;
  private Map<OperationKey, OperationData> operationData;
  private Set<String> referencedTypes;
  /**
   * Map of obfuscated ids to binary class names.
   */
  private Map<String, String> typeTokens;

  Deobfuscator() {
  }

  /**
   * Returns the client proxy types whose {@code @ProxyFor} is exactly
   * {@code binaryTypeName}. Ordered such that the most-derived types will be
   * iterated over first.
   */
  public List<String> getClientProxies(String binaryTypeName) {
    return domainToClientType.get(binaryTypeName);
  }

  /**
   * Returns a method descriptor that should be invoked on the service object.
   */
  public String getDomainMethodDescriptor(String operation) {
    OperationData data = getData(operation);
    return data == null ? null : data.getDomainMethodDescriptor();
  }

  public String getRequestContext(String operation) {
    OperationData data = getData(operation);
    return data == null ? null : data.getRequestContext();
  }

  public String getRequestContextMethodDescriptor(String operation) {
    OperationData data = getData(operation);
    return data == null ? null : data.getClientMethodDescriptor();
  }

  public String getRequestContextMethodName(String operation) {
    OperationData data = getData(operation);
    return data == null ? null : data.getMethodName();
  }

  /**
   * Returns a type's binary name based on an obfuscated token.
   */
  public String getTypeFromToken(String token) {
    return typeTokens.get(token);
  }

  public boolean isReferencedType(String name) {
    return referencedTypes.contains(name);
  }

  private OperationData getData(String operation) {
    OperationData data = operationData.get(new OperationKey(operation));
    return data;
  }
}
