/*
 * 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.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.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.RpcCommandVisitor;
import com.google.gwt.rpc.client.ast.ScalarValueCommand;
import com.google.gwt.rpc.client.ast.SetCommand;
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.rpc.server.CommandSerializationUtil.Accessor;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * This class will use ValueCommands to reconstitute objects.
 */
public class CommandServerSerializationStreamReader implements
    SerializationStreamReader {

  class Visitor extends RpcCommandVisitor {

    private final Stack<Object> values = new Stack<Object>();

    @Override
    public void endVisit(BooleanValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(ByteValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(CharValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(DoubleValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(EnumValueCommand x, Context ctx) {
      push(x, x.getValue());
    }

    @Override
    public void endVisit(FloatValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(IntValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(LongValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(NullValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(SetCommand x, Context ctx) {
      Exception ex;
      try {
        Field f = x.getFieldDeclClass().getDeclaredField(x.getField());
        Object value = values.pop();
        Object instance = values.peek();
        assert value == null
            || CommandSerializationUtil.getAccessor(f.getType()).canSet(
                value.getClass()) : "Cannot assign a "
            + value.getClass().getName() + " into " + f.getType().getName();

        CommandSerializationUtil.getAccessor(f.getType()).set(instance, f,
            value);
        return;
      } catch (SecurityException e) {
        ex = e;
      } catch (NoSuchFieldException e) {
        ex = e;
      }
      halt(new SerializationException("Unable to set field value", ex));
    }

    @Override
    public void endVisit(ShortValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public void endVisit(StringValueCommand x, Context ctx) {
      pushScalar(x);
    }

    @Override
    public boolean visit(ArrayValueCommand x, Context ctx) {
      if (maybePushBackRef(x)) {
        Object array = Array.newInstance(x.getComponentType(),
            x.getComponentValues().size());
        push(x, array);

        int size = x.getComponentValues().size();
        Accessor a = CommandSerializationUtil.getAccessor(x.getComponentType());
        for (int i = 0; i < size; i++) {
          accept(x.getComponentValues().get(i));
          a.set(array, i, values.pop());
        }
      }

      return false;
    }

    @Override
    public boolean visit(InstantiateCommand x, Context ctx) {
      if (maybePushBackRef(x)) {
        Object instance;
        try {
          instance = CommandSerializationUtil.allocateInstance(x.getTargetClass());
          push(x, instance);
          return true;
        } catch (InstantiationException e) {
          halt(new SerializationException("Unable to create instance", e));
        }
      }

      return false;
    }

    @Override
    public boolean visit(InvokeCustomFieldSerializerCommand x, Context ctx) {
      if (maybePushBackRef(x)) {

        CommandServerSerializationStreamReader subReader = new CommandServerSerializationStreamReader();
        subReader.prepareToRead(x.getValues());

        Class<?> serializerClass = x.getSerializerClass();
        assert serializerClass != null;

        Method instantiate = null;
        Method deserialize = null;
        for (Method m : serializerClass.getMethods()) {
          if ("instantiate".equals(m.getName())) {
            instantiate = m;
          } else if ("deserialize".equals(m.getName())) {
            deserialize = m;
          }

          if (instantiate != null && deserialize != null) {
            break;
          }
        }

        assert deserialize != null : "No deserialize method in "
            + serializerClass.getName();

        Object instance = null;
        if (instantiate != null) {
          assert Modifier.isStatic(instantiate.getModifiers()) : "instantiate method in "
              + serializerClass.getName() + " must be static";
          try {
            instance = instantiate.invoke(null, subReader);
          } catch (IllegalArgumentException e) {
            halt(new SerializationException("Unable to create instance", e));
          } catch (IllegalAccessException e) {
            halt(new SerializationException("Unable to create instance", e));
          } catch (InvocationTargetException e) {
            halt(new SerializationException("Unable to create instance", e));
          }
        } else {
          try {
            instance = x.getTargetClass().newInstance();
          } catch (InstantiationException e) {
            halt(new SerializationException("Unable to create instance", e));
          } catch (IllegalAccessException e) {
            halt(new SerializationException("Unable to create instance", e));
          }
        }

        assert instance != null : "Did not create instance";
        push(x, instance);

        // Process any additional fields
        accept(x.getSetters());

        try {
          deserialize.invoke(null, subReader, instance);
        } catch (IllegalArgumentException e) {
          halt(new SerializationException("Unable to deserialize instance", e));
        } catch (IllegalAccessException e) {
          halt(new SerializationException("Unable to deserialize instance", e));
        } catch (InvocationTargetException e) {
          halt(new SerializationException("Unable to deserialize instance", e));
        }
      }

      return false;
    }

    /**
     * Returns true if the command must be processed.
     */
    private boolean maybePushBackRef(IdentityValueCommand x) {
      Object instance = backRefs.get(x);
      if (instance == null) {
        return true;
      } else {
        values.push(instance);
        return false;
      }
    }

    private void push(IdentityValueCommand x, Object value) {
      assert !backRefs.containsKey(x) : "Trying to redefine a backref";
      backRefs.put(x, value);
      values.push(value);
    }

    private void pushScalar(ScalarValueCommand x) {
      values.push(x.getValue());
    }
  }

  Map<IdentityValueCommand, Object> backRefs = new HashMap<IdentityValueCommand, Object>();
  Iterator<ValueCommand> values;

  public void prepareToRead(List<ValueCommand> commands) {
    values = commands.iterator();
    assert values.hasNext() : "No commands";
  }

  public boolean readBoolean() throws SerializationException {
    return readNumberCommand(BooleanValueCommand.class).getValue();
  }

  public byte readByte() throws SerializationException {
    return readNumberCommand(ByteValueCommand.class).getValue();
  }

  public char readChar() throws SerializationException {
    return readNumberCommand(CharValueCommand.class).getValue();
  }

  public double readDouble() throws SerializationException {
    return readNumberCommand(DoubleValueCommand.class).getValue();
  }

  public float readFloat() throws SerializationException {
    return readNumberCommand(FloatValueCommand.class).getValue();
  }

  public int readInt() throws SerializationException {
    return readNumberCommand(IntValueCommand.class).getValue();
  }

  public long readLong() throws SerializationException {
    return readNumberCommand(LongValueCommand.class).getValue();
  }

  public Object readObject() throws SerializationException {
    ValueCommand command = readNextCommand(ValueCommand.class);
    Visitor v = new Visitor();
    v.accept(command);
    return v.values.pop();
  }

  public short readShort() throws SerializationException {
    return readNumberCommand(ShortValueCommand.class).getValue();
  }

  public String readString() throws SerializationException {
    return readNextCommand(StringValueCommand.class).getValue();
  }

  private <T extends ValueCommand> T readNextCommand(Class<T> clazz)
      throws SerializationException {
    if (!values.hasNext()) {
      throw new SerializationException("Reached end of stream");
    }
    ValueCommand next = values.next();
    if (!clazz.isInstance(next)) {
      throw new SerializationException("Cannot assign "
          + next.getClass().getName() + " to " + clazz.getName());
    }
    return clazz.cast(next);
  }

  /**
   * Will perform narrowing conversions from double type to other numeric types.
   */
  private <T extends ValueCommand> T readNumberCommand(Class<T> clazz)
      throws SerializationException {
    if (!values.hasNext()) {
      throw new SerializationException("Reached end of stream");
    }
    ValueCommand next = values.next();

    if (clazz.isInstance(next)) {
      return clazz.cast(next);
    } else if (next instanceof LongValueCommand) {
      if (!clazz.isInstance(next)) {
        throw new SerializationException("Cannot assign "
            + next.getClass().getName() + " to " + clazz.getName());
      }
      return clazz.cast(next);
    } else if (next instanceof DoubleValueCommand) {
      Exception ex;
      try {
        Constructor<T> c = clazz.getConstructor(double.class);
        return c.newInstance(((DoubleValueCommand) next).getValue().doubleValue());
      } catch (SecurityException e) {
        throw new SerializationException("Cannot construct ValueCommand type",
            e);
      } catch (NoSuchMethodException e) {
        throw new SerializationException("Connot initialize a "
            + clazz.getName() + " from a DoubleValueCommand", e);
      } catch (IllegalArgumentException e) {
        ex = e;
      } catch (InstantiationException e) {
        ex = e;
      } catch (IllegalAccessException e) {
        ex = e;
      } catch (InvocationTargetException e) {
        ex = e;
      }
      throw new SerializationException("Cannot create ValueCommand", ex);
    } else {
      throw new SerializationException(
          "Cannot create a numeric ValueCommand from a "
              + next.getClass().getName());
    }
  }
}
