/*
 * Copyright 1999-2011 Alibaba Group.
 *  
 * 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.alibaba.dubbo.common.serialize.support.dubbo;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.dubbo.common.io.ClassDescriptorMapper;
import com.alibaba.dubbo.common.serialize.ObjectInput;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.common.utils.StringUtils;

/**
 * Generic Object Input.
 * 
 * @author qian.lei
 */
public class GenericObjectInput extends GenericDataInput implements ObjectInput
{
	private static Object SKIPPED_OBJECT = new Object();

	private ClassDescriptorMapper mMapper;

	private List<Object> mRefs = new ArrayList<Object>();

	public GenericObjectInput(InputStream is)
	{
		this(is, Builder.DEFAULT_CLASS_DESCRIPTOR_MAPPER);
	}

	public GenericObjectInput(InputStream is, ClassDescriptorMapper mapper)
	{
		super(is);
		mMapper = mapper;
	}

	public GenericObjectInput(InputStream is, int buffSize)
	{
		this(is, buffSize, Builder.DEFAULT_CLASS_DESCRIPTOR_MAPPER);
	}

	public GenericObjectInput(InputStream is, int buffSize, ClassDescriptorMapper mapper)
	{
		super(is, buffSize);
		mMapper = mapper;
	}

	public Object readObject() throws IOException
	{
		String desc;
		byte b = read0();

		switch( b )
		{
			case OBJECT_NULL:
				return null;
			case OBJECT_DUMMY:
				return new Object();
			case OBJECT_DESC:
			{
				desc = readUTF();
				break;
			}
			case OBJECT_DESC_ID:
			{
				int index = readUInt();
				desc = mMapper.getDescriptor(index);
				if( desc == null )
					throw new IOException("Can not find desc id: " + index );
				break;
			}
			default:
				throw new IOException("Flag error, expect OBJECT_NULL|OBJECT_DUMMY|OBJECT_DESC|OBJECT_DESC_ID, get " + b);
		}
		try
		{
			Class<?> c = ReflectUtils.desc2class(desc);
			return Builder.register(c).parseFrom(this);
		}
		catch(ClassNotFoundException e)
		{
			throw new IOException("Read object failed, class not found. " + StringUtils.toString(e));
		}
	}
	
	@SuppressWarnings("unchecked")
	public <T> T readObject(Class<T> cls) throws IOException,ClassNotFoundException
	{
		return (T)readObject();
	}

    @SuppressWarnings("unchecked")
    public <T> T readObject(Class<T> cls, Type type) throws IOException,ClassNotFoundException
    {
        return (T)readObject();
    }

	public void addRef(Object obj)
	{
		mRefs.add(obj);
	}

	public Object getRef(int index) throws IOException
	{
		if( index < 0 || index >= mRefs.size() )
			return null;

		Object ret = mRefs.get(index);
		if( ret == SKIPPED_OBJECT )
			throw new IOException("Ref skipped-object.");
		return ret;
	}

	public void skipAny() throws IOException
	{
		byte b = read0();
		switch( b )
		{
			case VARINT_NF: case VARINT_NE: case VARINT_ND: case VARINT_NC: case VARINT_NB: case VARINT_NA: case VARINT_N9:
			case VARINT_N8: case VARINT_N7: case VARINT_N6: case VARINT_N5: case VARINT_N4: case VARINT_N3: case VARINT_N2: case VARINT_N1:
			case VARINT_0: case VARINT_1: case VARINT_2: case VARINT_3: case VARINT_4: case VARINT_5: case VARINT_6: case VARINT_7:
			case VARINT_8: case VARINT_9: case VARINT_A: case VARINT_B: case VARINT_C: case VARINT_D: case VARINT_E: case VARINT_F:
			case VARINT_10: case VARINT_11: case VARINT_12: case VARINT_13: case VARINT_14: case VARINT_15: case VARINT_16: case VARINT_17:
			case VARINT_18: case VARINT_19: case VARINT_1A: case VARINT_1B: case VARINT_1C: case VARINT_1D: case VARINT_1E: case VARINT_1F:
			case OBJECT_NULL: case OBJECT_DUMMY:
				break;
			case VARINT8:
			{
				read0();
				break;
			}
			case VARINT16:
			{
				read0(); read0();
				break;
			}
			case VARINT24:
			{
				read0(); read0(); read0();
				break;
			}
			case VARINT32:
			{
				read0(); read0(); read0(); read0();
				break;
			}
			case VARINT40:
			{
				read0(); read0(); read0(); read0(); read0();
				break;
			}
			case VARINT48:
			{
				read0(); read0(); read0(); read0(); read0(); read0();
				break;
			}
			case VARINT56:
			{
				read0(); read0(); read0(); read0(); read0(); read0(); read0();
				break;
			}
			case VARINT64:
			{
				read0(); read0(); read0(); read0(); read0(); read0(); read0(); read0();
				break;
			}
			case OBJECT:
			{
				addRef(SKIPPED_OBJECT);
				int len = readUInt();
				for(int i=0;i<len;i++)
					skipAny();
				break;
			}
			case OBJECT_REF:
			{
				readUInt();
				break;
			}
			case OBJECT_STREAM: case OBJECT_BYTES:
			{
				read0(readUInt());
				break;
			}
			case OBJECT_VALUE:
			{
				skipAny();
				break;
			}
			case OBJECT_VALUES:
			{
				int len = readUInt();
				for(int i=0;i<len;i++)
					skipAny();
				break;
			}
			case OBJECT_MAP:
			{
				int len = readUInt();
				for(int i=0;i<len;i++)
				{
					skipAny(); // skip key
					skipAny(); // skip value
				}
				break;
			}
			case OBJECT_DESC:
			{
				readUTF();
				int len = readUInt();
				for(int i=0;i<len;i++)
					skipAny();
				break;
			}
			case OBJECT_DESC_ID:
			{
				readUInt();
				int len = readUInt();
				for(int i=0;i<len;i++)
					skipAny();
				break;
			}
			default:
				throw new IOException("Flag error, get " + b);
		}
	}
}