/*
 * Copyright 2009 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.rpc.server;

import com.google.gwt.rpc.client.ast.CommandSink;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * Encapsulates data about the structure of the client code.
 */
public final class WebModeClientOracle extends ClientOracle implements
    Serializable {
  /*
   * TODO: Don't use Java serialization.
   */

  /**
   * A Builder object to create ClientOracles.
   */
  public static class Builder {
    private WebModeClientOracle oracle = new WebModeClientOracle();

    public void add(String jsIdent, String jsniIdent, String className,
        String memberName, int queryId, CastableTypeData castableTypeData,
        int seedId) {
      
      oracle.idents.add(jsIdent);
      ClassData data = oracle.getClassData(className);
      
      /*
       * Don't overwrite castableTypeData and queryId if already set.
       * There are many versions of symbols for a given className, 
       * corresponding to the type of member fields, etc.,
       * which don't have the queryId or castableTypeData initialized.  Only
       * the symbol data for the class itself has this info.
       */
      if (data.castableTypeData == null) {
        data.queryId = queryId;
        data.castableTypeData = castableTypeData;
      }
      
      if (jsniIdent == null || jsniIdent.length() == 0) {
        data.typeName = className;
        data.seedName = jsIdent;
        oracle.seedNamesToClassData.put(jsIdent, data);
        // Class.getName() with metadata disabled is "Class$S<seedId>"
        oracle.seedIdsToClassData.put("S" + seedId, data);
        data.seedId = seedId;
      } else {
        if (jsniIdent.contains("(")) {
          jsniIdent = jsniIdent.substring(jsniIdent.indexOf("::") + 2,
              jsniIdent.indexOf(')') + 1);
          data.methodJsniNamesToIdents.put(jsniIdent, jsIdent);
        } else {
          data.fieldIdentsToNames.put(jsIdent, memberName);
          data.fieldNamesToIdents.put(memberName, jsIdent);
        }
      }
    }

    public WebModeClientOracle getOracle() {
      WebModeClientOracle toReturn = oracle;
      oracle = null;
      return toReturn;
    }

    public void setSerializableFields(String className, List<String> fieldNames) {
      ClassData data = oracle.getClassData(className);
      assert data.serializableFields == null
          || fieldNames.containsAll(data.serializableFields);
      if (fieldNames.size() == 1) {
        data.serializableFields = Collections.singletonList(fieldNames.get(0));
      } else {
        data.serializableFields = new ArrayList<String>(fieldNames);
        Collections.sort(data.serializableFields);
      }
    }
  }

  /**
   * A pair with extra data.
   */
  public static class Triple<A, B, C> extends Pair<A, B> {
    private final C[] c;

    public Triple(A a, B b, C... c) {
      super(a, b);
      this.c = c;
    }

    public C[] getC() {
      return c;
    }
  }

  private static class ClassData implements Serializable {
    private static final long serialVersionUID = 5L;

    public CastableTypeData castableTypeData;
    public final Map<String, String> fieldIdentsToNames = new HashMap<String, String>();
    public final Map<String, String> fieldNamesToIdents = new HashMap<String, String>();
    public final Map<String, String> methodJsniNamesToIdents = new HashMap<String, String>();
    public int queryId;
    public String seedName;
    public List<String> serializableFields = Collections.emptyList();
    public String typeName;
    public int seedId;
  }

  /**
   * Defined to prevent simple changes from invalidating stored data.
   * 
   * TODO: Use something other than Java serialization to store this type's
   * data.
   */
  private static final long serialVersionUID = 2L;

  /**
   * Recreate a WebModeClientOracle based on the contents previously emitted by
   * {@link #store}. The underlying format should be considered opaque.
   */
  public static WebModeClientOracle load(InputStream stream) throws IOException {
    try {
      stream = new GZIPInputStream(stream);
      return readStreamAsObject(stream, WebModeClientOracle.class);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Should never reach this", e);
    }
  }

  static String jsniName(Class<?> clazz) {
    if (clazz.isPrimitive()) {
      if (clazz.equals(boolean.class)) {
        return "Z";
      } else if (clazz.equals(byte.class)) {
        return "B";
      } else if (clazz.equals(char.class)) {
        return "C";
      } else if (clazz.equals(short.class)) {
        return "S";
      } else if (clazz.equals(int.class)) {
        return "I";
      } else if (clazz.equals(long.class)) {
        return "J";
      } else if (clazz.equals(float.class)) {
        return "F";
      } else if (clazz.equals(double.class)) {
        return "D";
      }
      throw new RuntimeException("Unhandled primitive type " + clazz.getName());
    } else if (clazz.isArray()) {
      return "[" + jsniName(clazz.getComponentType());
    } else {
      return "L" + clazz.getName().replace('.', '/') + ";";
    }
  }

  /**
   * Copied from dev.Utility class which is not part of servlet.jar.
   */
  private static <T> T readStreamAsObject(InputStream inputStream, Class<T> type)
      throws ClassNotFoundException {
    ObjectInputStream objectInputStream = null;
    try {
      objectInputStream = new ObjectInputStream(inputStream);
      return type.cast(objectInputStream.readObject());
    } catch (IOException e) {
      return null;
    } finally {
      try {
        objectInputStream.close();
      } catch (IOException e) {
        // Ignore
      }
    }
  }

  /**
   * Serializes an object and writes it to a stream. Copied from Util to avoid
   * dependecy on gwt-dev.
   */
  private static void writeObjectToStream(OutputStream stream,
      Object... objects) throws IOException {
    ObjectOutputStream objectStream = new ObjectOutputStream(stream);
    for (Object object : objects) {
      objectStream.writeObject(object);
    }
    objectStream.flush();
  }

  /**
   * A map of class names to ClassData elements.
   */
  private final Map<String, ClassData> classData = new HashMap<String, ClassData>();

  private final Set<String> idents = new HashSet<String>();

  private final Map<String, ClassData> seedNamesToClassData = new HashMap<String, ClassData>();
  private final Map<String, ClassData> seedIdsToClassData = new HashMap<String, ClassData>();

  private transient Map<Class<?>, Field[]> operableFieldMap = new IdentityHashMap<Class<?>, Field[]>();

  /**
   * Instances of WebModeClientOracle are created either through the
   * {@link Builder} class or via the {@link #load} method.
   */
  protected WebModeClientOracle() {
  }

  @Override
  public CommandSink createCommandSink(OutputStream out) throws IOException {
    return new WebModePayloadSink(this, out);
  }

  @Override
  public String createUnusedIdent(String ident) {
    while (idents.contains(ident)) {
      ident += "$";
    }
    return ident;
  }
  
  @Override
  public CastableTypeData getCastableTypeData(Class<?> clazz) {
    while (clazz != null) {
      CastableTypeData toReturn = getCastableTypeData(canonicalName(clazz));
      if (toReturn != null) {
        return toReturn;
      }
      clazz = clazz.getSuperclass();
    }
    return null;
  }

  @Override
  public String getFieldId(Class<?> clazz, String fieldName) {
    while (clazz != null) {
      String className = clazz.getName();
      ClassData data = getClassData(className);
      if (data.fieldNamesToIdents.containsKey(fieldName)) {
        return data.fieldNamesToIdents.get(fieldName);
      }
      clazz = clazz.getSuperclass();
    }
    return null;
  }

  @Override
  public String getFieldId(Enum<?> value) {
    return getFieldId(value.getDeclaringClass(), value.name());
  }

  @Override
  public String getFieldId(String className, String fieldName) {
    ClassData data = getClassData(className);
    return data.fieldNamesToIdents.get(fieldName);
  }

  @Override
  public Pair<Class<?>, String> getFieldName(Class<?> clazz, String fieldId) {
    while (clazz != null) {
      ClassData data = getClassData(clazz.getName());
      String fieldName = data.fieldIdentsToNames.get(fieldId);
      if (fieldName == null) {
        clazz = clazz.getSuperclass();
      } else {
        return new Pair<Class<?>, String>(clazz, fieldName);
      }
    }
    return null;
  }

  /**
   * This will search superclasses.
   */
  @Override
  public String getMethodId(Class<?> clazz, String methodName, Class<?>... args) {
    while (clazz != null) {
      String toReturn = getMethodId(clazz.getName(), methodName, args);
      if (toReturn != null) {
        return toReturn;
      }
      clazz = clazz.getSuperclass();
    }
    return null;
  }

  @Override
  public String getMethodId(String className, String methodName,
      String... jsniArgTypes) {
    StringBuilder sb = new StringBuilder();
    sb.append(methodName);
    sb.append("(");
    for (String jsniArg : jsniArgTypes) {
      sb.append(jsniArg);
    }
    sb.append(")");

    ClassData data = getClassData(className);
    String jsIdent = data.methodJsniNamesToIdents.get(sb.toString());
    return jsIdent;
  }

  @Override
  public Field[] getOperableFields(Class<?> clazz) {
    Field[] toReturn;
    synchronized (operableFieldMap) {
      toReturn = operableFieldMap.get(clazz);
    }
    if (toReturn != null) {
      return toReturn;
    }

    ClassData data = getClassData(clazz.getName());
    toReturn = new Field[data.serializableFields.size()];
    for (int i = 0; i < toReturn.length; i++) {
      String fieldName = data.serializableFields.get(i);
      try {
        toReturn[i] = clazz.getDeclaredField(fieldName);
      } catch (SecurityException e) {
        throw new IncompatibleRemoteServiceException("Cannot access field "
            + fieldName, e);
      } catch (NoSuchFieldException e) {
        throw new IncompatibleRemoteServiceException("No field " + fieldName, e);
      }
    }

    synchronized (operableFieldMap) {
      operableFieldMap.put(clazz, toReturn);
    }
    return toReturn;
  }

  @Override
  public int getQueryId(Class<?> clazz) {
    while (clazz != null) {
      int toReturn = getQueryId(canonicalName(clazz));
      if (toReturn != 0) {
        return toReturn;
      }
      clazz = clazz.getSuperclass();
    }
    return 0;
  }

  @Override
  public String getSeedName(Class<?> clazz) {
    ClassData data = getClassData(clazz.getName());
    return data.seedName;
  }

  @Override
  public String getTypeName(String seedName) {
    // TODO: Decide how to handle the no-metadata case
    ClassData data = null;
    if (seedName.startsWith("Class$")) {
      seedName = seedName.substring(6);
      data = seedIdsToClassData.get(seedName);
    }

    if (data == null) {
      data = seedNamesToClassData.get(seedName);
    }
    return data == null ? null : data.typeName;
  }

  @Override
  public boolean isScript() {
    return true;
  }

  /**
   * Write the state of the WebModeClientOracle into an OutputStream. The
   * underlying format should be considered opaque.
   */
  public void store(OutputStream stream) throws IOException {
    stream = new GZIPOutputStream(stream);
    writeObjectToStream(stream, this);
    stream.close();
  }

  private String canonicalName(Class<?> clazz) {
    if (clazz.isArray()) {
      Class<?> leafType = clazz;
      do {
        leafType = leafType.getComponentType();
      } while (leafType.isArray());

      Class<?> enclosing = leafType.getEnclosingClass();
      if (enclosing != null) {
        // com.foo.Enclosing$Name[]
        return canonicalName(enclosing) + "$" + clazz.getSimpleName();
      } else if (leafType.getPackage() == null) {
        // Name0[
        return clazz.getSimpleName();
      } else {
        // com.foo.Name[]
        return leafType.getPackage().getName() + "." + clazz.getSimpleName();
      }
    } else {
      return clazz.getName();
    }
  }
  
  private CastableTypeData getCastableTypeData(String className) {
    ClassData data = getClassData(className);
    return data.castableTypeData;
  }

  private ClassData getClassData(String className) {
    ClassData toReturn = classData.get(className);
    if (toReturn == null) {
      toReturn = new ClassData();
      classData.put(className, toReturn);
    }
    return toReturn;
  }

  /**
   * This will not search superclasses and is used to access magic GWT types
   * like Array.
   */
  private String getMethodId(String className, String methodName,
      Class<?>... args) {
    String[] jsniArgTypes = new String[args.length];
    for (int i = 0, j = args.length; i < j; i++) {
      jsniArgTypes[i] = jsniName(args[i]);
    }
    return getMethodId(className, methodName, jsniArgTypes);
  }

  private int getQueryId(String className) {
    ClassData data = getClassData(className);
    return data.queryId;
  }

  /**
   * Reinitialize the <code>operableFieldMap</code> field when the
   * WebModeClientOracle is reloaded.
   */
  private Object readResolve() {
    operableFieldMap = new HashMap<Class<?>, Field[]>();
    return this;
  }
}
