/*
 * 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.ObjectStreamException;
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 typeId) {
      oracle.idents.add(jsIdent);
      ClassData data = oracle.getClassData(className);
      data.typeId = typeId;
      if (jsniIdent == null || jsniIdent.length() == 0) {
        data.typeName = className;
        data.seedName = jsIdent;
        oracle.seedNamesToClassData.put(jsIdent, data);
      } 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 = 3L;

    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 String seedName;
    public List<String> serializableFields = Collections.emptyList();
    public String typeName;
    public int typeId;
  }

  /**
   * 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 = 1L;

  /**
   * 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 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 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 String getSeedName(Class<?> clazz) {
    ClassData data = getClassData(clazz.getName());
    return data.seedName;
  }

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

  @Override
  public String getTypeName(String seedName) {
    // TODO: Decide how to handle the no-metadata case
    if (seedName.startsWith("Class$")) {
      seedName = seedName.substring(6);
    }
    ClassData 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 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 getTypeId(String className) {
    ClassData data = getClassData(className);
    return data.typeId;
  }

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