/*
 * 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 static com.google.gwt.rpc.client.impl.SimplePayloadSink.ARRAY_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.BACKREF_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.BOOLEAN_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.BYTE_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.CHAR_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.DOUBLE_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.ENUM_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.FLOAT_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.INT_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.INVOKE_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.LONG_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.NL_CHAR;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.OBJECT_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.RETURN_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.RPC_SEPARATOR_CHAR;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.SHORT_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.STRING_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.THROW_TYPE;
import static com.google.gwt.rpc.client.impl.SimplePayloadSink.VOID_TYPE;

import com.google.gwt.rpc.client.ast.ArrayValueCommand;
import com.google.gwt.rpc.client.ast.BooleanValueCommand;
import com.google.gwt.rpc.client.ast.ByteValueCommand;
import com.google.gwt.rpc.client.ast.CharValueCommand;
import com.google.gwt.rpc.client.ast.DoubleValueCommand;
import com.google.gwt.rpc.client.ast.EnumValueCommand;
import com.google.gwt.rpc.client.ast.FloatValueCommand;
import com.google.gwt.rpc.client.ast.HasSetters;
import com.google.gwt.rpc.client.ast.IdentityValueCommand;
import com.google.gwt.rpc.client.ast.InstantiateCommand;
import com.google.gwt.rpc.client.ast.IntValueCommand;
import com.google.gwt.rpc.client.ast.InvokeCustomFieldSerializerCommand;
import com.google.gwt.rpc.client.ast.LongValueCommand;
import com.google.gwt.rpc.client.ast.NullValueCommand;
import com.google.gwt.rpc.client.ast.ReturnCommand;
import com.google.gwt.rpc.client.ast.RpcCommand;
import com.google.gwt.rpc.client.ast.ScalarValueCommand;
import com.google.gwt.rpc.client.ast.ShortValueCommand;
import com.google.gwt.rpc.client.ast.StringValueCommand;
import com.google.gwt.rpc.client.ast.ValueCommand;
import com.google.gwt.user.server.rpc.impl.SerializabilityUtil;

import java.lang.reflect.Array;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * Decodes the simple payload.
 */
public class SimplePayloadDecoder {
  private static final String OBFUSCATED_CLASS_PREFIX = "Class$ ";
  private static final Map<String, Class<?>> PRIMITIVE_TYPES = new HashMap<String, Class<?>>();

  static {
    // Obfuscated when class metadata is disabled
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + BOOLEAN_TYPE, boolean.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + BYTE_TYPE, byte.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + CHAR_TYPE, char.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + DOUBLE_TYPE, double.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + FLOAT_TYPE, float.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + INT_TYPE, int.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + LONG_TYPE, long.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + SHORT_TYPE, short.class);
    PRIMITIVE_TYPES.put(OBFUSCATED_CLASS_PREFIX + VOID_TYPE, void.class);

    // Regular
    PRIMITIVE_TYPES.put(boolean.class.getName(), boolean.class);
    PRIMITIVE_TYPES.put(byte.class.getName(), byte.class);
    PRIMITIVE_TYPES.put(char.class.getName(), char.class);
    PRIMITIVE_TYPES.put(double.class.getName(), double.class);
    PRIMITIVE_TYPES.put(float.class.getName(), float.class);
    PRIMITIVE_TYPES.put(int.class.getName(), int.class);
    PRIMITIVE_TYPES.put(long.class.getName(), long.class);
    PRIMITIVE_TYPES.put(short.class.getName(), short.class);
    PRIMITIVE_TYPES.put(void.class.getName(), void.class);
  }

  private final Map<Integer, ValueCommand> backRefs = new HashMap<Integer, ValueCommand>();
  private final Map<String, Class<?>> classCache = new HashMap<String, Class<?>>(
      PRIMITIVE_TYPES);
  private final ClientOracle clientOracle;
  private final Stack<RpcCommand> commands = new Stack<RpcCommand>();
  private int idx;
  private final CharSequence payload;
  private ReturnCommand toReturn;
  private ValueCommand toThrow;

  /**
   * Construct a new SimplePayloadDecoder. This will consume the entire payload
   * which will be made available through {@link #getValues}. If the payload
   * stream contains an embedded exception, processing will end early and the
   * Throwable will be available via {@link #getThrownValue()}.
   * 
   * @throws ClassNotFoundException
   */
  public SimplePayloadDecoder(ClientOracle clientOracle, CharSequence payload)
      throws ClassNotFoundException {
    this.clientOracle = clientOracle;
    this.payload = payload;
    while (toReturn == null && idx < payload.length()) {
      decodeCommand();

      // We hit an error in the stream; stop now
      if (toThrow != null) {
        return;
      }
    }
  }

  /**
   * Returns the thrown value, if any.
   */
  public ValueCommand getThrownValue() {
    return toThrow;
  }

  /**
   * Returns the values encoded in the payload.
   */
  public List<ValueCommand> getValues() {
    return toReturn == null ? Collections.<ValueCommand> emptyList()
        : toReturn.getValues();
  }

  private void decodeCommand() throws ClassNotFoundException {
    char command = next();
    if (command == NL_CHAR) {
      // Pretty mode payload
      command = next();
    }
    String token = token();
    switch (command) {
      case BOOLEAN_TYPE: {
        push(new BooleanValueCommand(token.equals("1")));
        break;
      }
      case BYTE_TYPE: {
        push(new ByteValueCommand(Byte.valueOf(token)));
        break;
      }
      case CHAR_TYPE: {
        push(new CharValueCommand(Character.valueOf((char) Integer.valueOf(
            token).intValue())));
        break;
      }
      case DOUBLE_TYPE: {
        push(new DoubleValueCommand(Double.valueOf(token)));
        break;
      }
      case FLOAT_TYPE: {
        push(new FloatValueCommand(Float.valueOf(token)));
        break;
      }
      case INT_TYPE: {
        push(new IntValueCommand(Integer.valueOf(token)));
        break;
      }
      case LONG_TYPE: {
        push(new LongValueCommand(Long.valueOf(token)));
        break;
      }
      case VOID_TYPE: {
        push(NullValueCommand.INSTANCE);
        break;
      }
      case SHORT_TYPE: {
        push(new ShortValueCommand(Short.valueOf(token)));
        break;
      }
      case STRING_TYPE: {
        // "4~abcd
        int length = Integer.valueOf(token);
        String value = next(length);
        if (next() != RPC_SEPARATOR_CHAR) {
          throw new RuntimeException("Overran string");
        }
        push(new StringValueCommand(value));
        break;
      }
      case ENUM_TYPE: {
        // ETypeSeedName~IOrdinal~
        EnumValueCommand x = new EnumValueCommand();
        push(x);
        
        // use ordinal (and not name), since name might have been obfuscated
        int ordinal = readCommand(IntValueCommand.class).getValue();

        @SuppressWarnings("unchecked")
        Class<? extends Enum> clazz = findClass(token).asSubclass(Enum.class);
        
        /*
         * TODO: Note this approach could be prone to subtle corruption or
         * an ArrayOutOfBoundsException if the client and server have drifted.
         */
        Enum<?> enumConstants[] = clazz.getEnumConstants();
        x.setValue(enumConstants[ordinal]);
        break;
      }
      case ARRAY_TYPE: {
        // Encoded as (leafType, dimensions, length, .... )
        Class<?> leaf = findClass(token);

        Integer numDims = readCommand(IntValueCommand.class).getValue();
        Class<?> clazz;
        if (numDims > 1) {
          int[] dims = new int[numDims - 1];
          clazz = Array.newInstance(leaf, dims).getClass();
        } else {
          clazz = leaf;
        }

        ArrayValueCommand x = new ArrayValueCommand(clazz);
        push(x);
        int length = readCommand(IntValueCommand.class).getValue();
        for (int i = 0; i < length; i++) {
          x.add(readCommand(ValueCommand.class));
        }
        break;
      }
      case OBJECT_TYPE: {
        // @TypeSeedName~3~... N-many setters ...
        Class<?> clazz = findClass(token);
        InstantiateCommand x = new InstantiateCommand(clazz);
        push(x);
        readSetters(clazz, x);
        break;
      }
      case INVOKE_TYPE: {
        // !TypeSeedName~Number of objects written by CFS~...CFS objects...~
        // Number of extra fields~...N-many setters...
        Class<?> clazz = findClass(token);
        Class<?> serializerClass = null;

        // The custom serializer type might be for a supertype
        Class<?> manualType = clazz;
        while (manualType != null) {
          serializerClass = SerializabilityUtil.hasCustomFieldSerializer(manualType);
          if (serializerClass != null) {
            break;
          }
          manualType = manualType.getSuperclass();
        }

        InvokeCustomFieldSerializerCommand x = new InvokeCustomFieldSerializerCommand(
            clazz, serializerClass, manualType);
        push(x);

        readFields(x);
        readSetters(clazz, x);
        break;
      }
      case RETURN_TYPE: {
        // R4~...values...
        toReturn = new ReturnCommand();
        int toRead = Integer.valueOf(token);
        for (int i = 0; i < toRead; i++) {
          toReturn.addValue(readCommand(ValueCommand.class));
        }
        break;
      }
      case THROW_TYPE: {
        // T...value...
        toThrow = readCommand(ValueCommand.class);
        break;
      }
      case BACKREF_TYPE: {
        // @backrefNumber~
        ValueCommand x = backRefs.get(Integer.valueOf(token));
        assert x != null : "Could not find backref";
        commands.push(x);
        break;
      }
      case RPC_SEPARATOR_CHAR: {
        /*
         * Not strictly necessary, but it makes an off-by-one easier to
         * distinguish.
         */
        throw new RuntimeException("Segmentation overrun at " + idx);
      }
      default:
        throw new RuntimeException("Unknown command " + command);
    }
  }

  /**
   * Uses the ClientOracle to decode a type name.
   */
  private Class<?> findClass(String token) throws ClassNotFoundException {
    /*
     * NB: This is the only method in SimplePayloadDecoder which would require
     * any real adaptation to be made to run in web mode.
     */

    Class<?> clazz = classCache.get(token);
    if (clazz != null) {
      return clazz;
    }

    String className = clientOracle.getTypeName(token);
    if (className == null) {
      // Probably a regular class name
      className = token;
    }

    if (className.contains("[]")) {
      // Array types are annoying to construct
      int firstIndex = -1;
      int j = -1;
      int dims = 0;
      while ((j = className.indexOf("[", j + 1)) != -1) {
        if (dims++ == 0) {
          firstIndex = j;
        }
      }
      Class<?> componentType = findClass(className.substring(0, firstIndex));
      assert componentType != null : "Could not determine component type with "
          + className.substring(0, firstIndex);
      clazz = Array.newInstance(componentType, new int[dims]).getClass();
    } else {
      // Ensure that we use the bridge classloader in CCL
      ClassLoader myCCL = getClass().getClassLoader();
      clazz = Class.forName(className, false, myCCL);
    }
    classCache.put(token, clazz);
    return clazz;
  }

  /**
   * Reads the next character in the input, possibly evaluating escape
   * sequences.
   */
  private char next() {
    char c = payload.charAt(idx++);

    if (c == '\\') {
      switch (payload.charAt(idx++)) {
        case '0':
          c = '\0';
          break;
        case '!':
          // Compatibility since we're using the legacy escaping code
          c = '|';
          break;
        case 'b':
          c = '\b';
          break;
        case 't':
          c = '\t';
          break;
        case 'n':
          c = '\n';
          break;
        case 'f':
          c = '\f';
          break;
        case 'r':
          c = '\r';
          break;
        case '\\':
          c = '\\';
          break;
        case '"':
          c = '"';
          break;
        case 'u':
          c = (char) Integer.parseInt(
              payload.subSequence(idx, idx += 4).toString(), 16);
          break;
        case 'x':
          c = (char) Integer.parseInt(
              payload.subSequence(idx, idx += 2).toString(), 16);
          break;
        default:
          throw new RuntimeException("Unhandled escape " + payload.charAt(idx));
      }
    }
    return c;
  }

  /**
   * Reads <code>count</code> many characters and returns them as a string.
   */
  private String next(int count) {
    StringBuilder sb = new StringBuilder();
    while (count-- > 0) {
      sb.append(next());
    }
    return sb.toString();
  }

  /**
   * Retains the object value and establishes a backreference.
   */
  private void push(IdentityValueCommand x) {
    commands.push(x);
    backRefs.put(backRefs.size(), x);
  }

  /**
   * Retains the scalar value, but does not establish a backreference.
   */
  private void push(ScalarValueCommand x) {
    commands.push(x);
  }

  /**
   * Retains the string value and establishes a backreference.
   */
  private void push(StringValueCommand x) {
    commands.push(x);
    backRefs.put(backRefs.size(), x);
  }

  /**
   * Read one command from the stream.
   * 
   * @param <T> the expected type of RpcCommand to read
   * @param clazz the expected type of RpcCommand to read
   * @throws ClassCastException if a command was successfully read, but could
   *           not be assigned to <code>clazz</code>
   */
  private <T extends RpcCommand> T readCommand(Class<T> clazz)
      throws ClassNotFoundException {
    decodeCommand();
    RpcCommand value = commands.pop();
    assert clazz.isInstance(value) : "Cannot assign a "
        + value.getClass().getName() + " to " + clazz.getName();
    return clazz.cast(value);
  }

  /**
   * Format is (int, value...).
   */
  private void readFields(InvokeCustomFieldSerializerCommand x)
      throws ClassNotFoundException {
    int length = readCommand(IntValueCommand.class).getValue();
    for (int i = 0; i < length; i++) {
      x.addValue(readCommand(ValueCommand.class));
    }
  }

  /**
   * Format is (fieldDeclClassName, fieldId, value). fieldDeclClassName may be
   * null.
   */
  private void readSetter(Class<?> clazz, HasSetters x)
      throws ClassNotFoundException {
    // Only used by hosted mode to handle shadowing
    if (!clientOracle.isScript()) {
      String fieldDeclClassName = readCommand(StringValueCommand.class).getValue();
      if (fieldDeclClassName != null) {
        clazz = findClass(fieldDeclClassName);
      }
    }
    String fieldId = readCommand(StringValueCommand.class).getValue();

    Pair<Class<?>, String> data = clientOracle.getFieldName(clazz, fieldId);
    Class<?> fieldDeclClass = data.getA();
    String fieldName = data.getB();
    ValueCommand value = readCommand(ValueCommand.class);
    x.set(fieldDeclClass, fieldName, value);
  }

  /**
   * Format is (int, setter...).
   */
  private void readSetters(Class<?> clazz, HasSetters x)
      throws ClassNotFoundException {
    int length = readCommand(IntValueCommand.class).getValue();
    for (int i = 0; i < length; i++) {
      readSetter(clazz, x);
    }
  }

  /**
   * Read through the next separator character.
   */
  private String token() {
    StringBuilder sb = new StringBuilder();
    char n = next();
    while (n != RPC_SEPARATOR_CHAR) {
      sb.append(n);
      n = next();
    }
    return sb.toString();
  }
}
