/*
 * 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.ArrayValueCommand;
import com.google.gwt.rpc.client.ast.CommandSink;
import com.google.gwt.rpc.client.ast.EnumValueCommand;
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.InvokeCustomFieldSerializerCommand;
import com.google.gwt.rpc.client.ast.NullValueCommand;
import com.google.gwt.rpc.client.ast.ValueCommand;
import com.google.gwt.rpc.client.impl.CommandSerializationStreamWriterBase;
import com.google.gwt.rpc.client.impl.HasValuesCommandSink;
import com.google.gwt.rpc.server.CommandSerializationUtil.Accessor;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.impl.SerializabilityUtil;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * A server-side implementation of SerializationStreamWriter that creates a
 * command stream.
 */
public class CommandServerSerializationStreamWriter extends
    CommandSerializationStreamWriterBase {

  private final ClientOracle clientOracle;
  private final Map<Object, IdentityValueCommand> identityMap = new IdentityHashMap<Object, IdentityValueCommand>();

  public CommandServerSerializationStreamWriter(CommandSink sink) {
    this(new HostedModeClientOracle(), sink);
  }

  public CommandServerSerializationStreamWriter(ClientOracle oracle,
      CommandSink sink) {
    super(sink);
    this.clientOracle = oracle;
  }

  /**
   * Type is passed in to handle primitive types.
   */
  @Override
  protected ValueCommand makeValue(Class<?> type, Object value)
      throws SerializationException {
    if (value == null) {
      return NullValueCommand.INSTANCE;
    }

    Accessor accessor;

    if (identityMap.containsKey(value)) {
      return identityMap.get(value);

    } else if ((accessor = CommandSerializationUtil.getAccessor(type)).canMakeValueCommand()) {
      return accessor.makeValueCommand(value);

    } else if (type.isArray()) {
      return makeArray(type, value);

    } else if (Enum.class.isAssignableFrom(type)) {
      return makeEnum(value);

    } else {
      return makeObject(type, value);
    }
  }

  private ArrayValueCommand makeArray(Class<?> type, Object value)
      throws SerializationException {
    ArrayValueCommand toReturn = new ArrayValueCommand(type.getComponentType());
    for (int i = 0, j = Array.getLength(value); i < j; i++) {
      Object arrayValue = Array.get(value, i);
      if (arrayValue == null) {
        toReturn.add(NullValueCommand.INSTANCE);
      } else {
        Class<? extends Object> valueType = type.getComponentType().isPrimitive()
            ? type.getComponentType() : arrayValue.getClass();
        toReturn.add(makeValue(valueType, arrayValue));
      }
    }
    identityMap.put(value, toReturn);
    return toReturn;
  }

  private ValueCommand makeEnum(Object value) {
    EnumValueCommand toReturn = new EnumValueCommand();
    toReturn.setValue((Enum<?>) value);
    return toReturn;
  }

  /*
   * TODO: Profiling shows that the reflection and conditional logic in this
   * method is a hotspot. This could be remedied by generating synthetic
   * InstantiateCommand types that initialize themselves.
   */
  private IdentityValueCommand makeObject(Class<?> type, Object value)
      throws SerializationException {

    if (type.isAnonymousClass() || type.isLocalClass()) {
      throw new SerializationException(
          "Cannot serialize anonymous or local classes");
    }

    Class<?> manualType = type;
    Class<?> customSerializer;
    do {
      customSerializer = SerializabilityUtil.hasCustomFieldSerializer(manualType);
      if (customSerializer != null) {
        break;
      }
      manualType = manualType.getSuperclass();
    } while (manualType != null);

    IdentityValueCommand ins;
    if (customSerializer != null) {
      ins = serializeWithCustomSerializer(customSerializer, value, type,
          manualType);
    } else {
      ins = new InstantiateCommand(type);
      identityMap.put(value, ins);
    }

    /*
     * If we're looking at a subclass of a manually-serialized type, the
     * subclass must be tagged as serializable in order to qualify for
     * serialization.
     */
    if (type != manualType) {
      if (!Serializable.class.isAssignableFrom(type)
          && !IsSerializable.class.isAssignableFrom(type)) {
        throw new SerializationException(type.getName()
            + " is not a serializable type");
      }
    }

    while (type != manualType) {
      Field[] serializableFields = clientOracle.getOperableFields(type);
      for (Field declField : serializableFields) {
        assert (declField != null);

        Accessor accessor = CommandSerializationUtil.getAccessor(declField.getType());
        ValueCommand valueCommand;
        Object fieldValue = accessor.get(value, declField);
        if (fieldValue == null) {
          valueCommand = NullValueCommand.INSTANCE;
        } else {
          Class<? extends Object> fieldType = declField.getType().isPrimitive()
              ? declField.getType() : fieldValue.getClass();
          valueCommand = makeValue(fieldType, fieldValue);
        }

        ((HasSetters) ins).set(declField.getDeclaringClass(),
            declField.getName(), valueCommand);
      }
      type = type.getSuperclass();
    }
    return ins;
  }

  private InvokeCustomFieldSerializerCommand serializeWithCustomSerializer(
      Class<?> customSerializer, Object instance, Class<?> instanceClass,
      Class<?> manuallySerializedType) throws SerializationException {
    assert !instanceClass.isArray();

    Exception ex;
    try {
      /*
       * NB: Class.getMethod() wants exact formal types. It may be the case that
       * the custom serializer uses looser type bounds in its method
       * declarations.
       */
      for (Method method : customSerializer.getMethods()) {
        if ("serialize".equals(method.getName())) {
          assert Modifier.isStatic(method.getModifiers()) : "serialize method "
              + "in type " + customSerializer.getName() + " must be static";

          final InvokeCustomFieldSerializerCommand toReturn = new InvokeCustomFieldSerializerCommand(
              instanceClass, customSerializer, manuallySerializedType);
          identityMap.put(instance, toReturn);

          CommandServerSerializationStreamWriter subWriter = new CommandServerSerializationStreamWriter(
              clientOracle, new HasValuesCommandSink(toReturn));
          method.invoke(null, subWriter, instance);

          return toReturn;
        }
      }

      throw new NoSuchMethodException(
          "Could not find serialize method in custom serializer "
              + customSerializer.getName());

    } catch (SecurityException e) {
      ex = e;
    } catch (NoSuchMethodException e) {
      ex = e;
    } catch (IllegalArgumentException e) {
      ex = e;
    } catch (IllegalAccessException e) {
      ex = e;
    } catch (InvocationTargetException e) {
      ex = e;
    }

    throw new SerializationException(ex);
  }
}
