package com.hmsoft.remote.rmi.handler;

import org.apache.log4j.Logger;
import com.hmsoft.remote.rmi.common.utils.StringUtils;
import com.hmsoft.remote.rmi.exception.RemotingException;
import com.hmsoft.remote.rmi.future.TransFuture;
import com.hmsoft.remote.rmi.model.Request;
import com.hmsoft.remote.rmi.model.Response;
import com.hmsoft.remote.rmi.transport.NettyChannel;

/**
 * 
 * HeaderExchangeHandler
 *
 */
public class HeaderExchangeHandler implements ChannelHandler {

    protected static final Logger logger  = Logger.getLogger(HeaderExchangeHandler.class);

    private final ExchangeHandler handler;

    public HeaderExchangeHandler(ExchangeHandler handler){
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        this.handler = handler;
    }
    
    /**
     * <p>处理client端的请求</p>
     * @param channel
     * @param req
     * @return Response
     * @throws RemotingException
     */
    private Response handleRequest(NettyChannel channel, Request req) throws RemotingException {
        Response res = new Response(req.getId(), req.getVersion());
        // find handler by message class.
        Object msg = req.getData();
        try {
            // handle data.
            Object result = handler.reply(channel, msg);
            res.setStatus(Response.OK);
            res.setResult(result);
        } catch (Throwable e) {
            res.setStatus(Response.SERVICE_ERROR);
            res.setErrMsg(StringUtils.toString(e));
        }
        return res;
    }

    private static void handleResponse(NettyChannel channel, Response response) throws RemotingException {
        if (response != null && !response.isHeartbeat()) {
            TransFuture.received(channel, response);
        }
    }

    public void connected(NettyChannel channel) throws RemotingException {
        try {
            handler.connected(channel);
        } finally {
        }
    }

    public void disconnected(NettyChannel channel) throws RemotingException {
        try {
            handler.disconnected(channel);
        } finally {
        }
    }

    public void sent(NettyChannel channel, Object message) throws RemotingException {
        Throwable exception = null;
        try {
            try {
                handler.sent(channel, message);
            } finally {
            }
        } catch (Throwable t) {
            exception = t;
        }
        if (message instanceof Request) {
            Request request = (Request) message;
            TransFuture.sent(channel, request);
        }
        if (exception != null) {
            if (exception instanceof RuntimeException) {
                throw (RuntimeException) exception;
            } else if (exception instanceof RemotingException) {
                throw (RemotingException) exception;
            } else {
                throw new RemotingException(exception.getMessage());
            }
        }
    }

    public void received(NettyChannel channel, Object message) throws RemotingException {
        try {
            if (message instanceof Request) {
                // handle request.
                Request request = (Request) message;
                if (request.isTwoWay()) {
                    Response response = handleRequest(channel, request);
                    channel.send(response);
                } 
                else {
                    handler.received(channel, request.getData());
                }
            } 
            else if (message instanceof Response) {
                handleResponse(channel, (Response) message);
            }    	
        } 
        finally {
        	
        }
    }

    public void caught(NettyChannel channel, Throwable exception) throws RemotingException {}

}
