/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you 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.eactive.eai.rms.onl.server;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.io.StreamCorruptedException;
import java.util.List;

import org.apache.log4j.Logger;

import com.eactive.eai.adapter.socket2.common.CommonLib;
import com.eactive.eai.rms.onl.server.handler.TransactionSendHandler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageDecoder;

/**
 * A UDP server that responds to the QOTM (quote of the moment) request to a {@link QuoteOfTheMomentClient}.
 *
 * Inspired by <a href="http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
 * Java tutorial</a>.
 */
public final class ObjectUdpDecoder extends MessageToMessageDecoder<DatagramPacket>{
	private static final Logger logger = Logger.getLogger(TransactionSendHandler.class);
	
	@Override
	protected void decode(ChannelHandlerContext ctx, DatagramPacket msg,List<Object> out) throws Exception {
		// TODO Auto-generated method stub
		ByteBuf buf = msg.content();
		int i = buf.getInt(0);
		int r = buf.readableBytes();
		if (i+4==r){
			byte[] b = new byte[i];
			try {
				buf.getBytes(4, b);
				Object obj = getObject(Thread.currentThread().getContextClassLoader(), b);
				out.add(obj);
			}catch(Exception e) {
				logger.error("ObjectUdpDecoder context :"+ ctx + " recv data : " + new String(b) + CommonLib.hexDump(b));
				throw e;
			}
		}else{
			//System.out.println("false " + i + "," + r +msg.content().toString(CharsetUtil.UTF_8));
		}

		//System.out.println("i="+i +"r="+r+","+ buf.toString(CharsetUtil.UTF_8));
		
		
	}
	
	private Object getObject(final ClassLoader classLoader,byte[] buffer)throws Exception{
        Object obj;
        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buffer)) {
	        protected ObjectStreamClass readClassDescriptor()
	            throws IOException, ClassNotFoundException{
	            int type = read();
	            if(type < 0)
	                throw new EOFException();
	            switch(type)
	            {
	            case 0: // '\0'
	                return super.readClassDescriptor();
	
	            case 1: // '\001'
	                String className = readUTF();
	                Class clazz = Class.forName(className, true, classLoader);
	                return ObjectStreamClass.lookup(clazz);
	            }
	            throw new StreamCorruptedException((new StringBuilder()).append("Unexpected class descriptor type: ").append(type).toString());
	        }
	
	        protected Class resolveClass(ObjectStreamClass desc)
	            throws IOException, ClassNotFoundException
	        {
	            String name = desc.getName();
	            try
	            {
	                return Class.forName(name, false, classLoader);
	            }
	            catch(ClassNotFoundException ex)
	            {
	                return super.resolveClass(desc);
	            }
	        }
	
	    };
	    obj = in.readObject();
	    return obj;
	}
}
