/*
 * 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 (String) readObject();
  }

  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());
    }
  }
}
