package com.nokia.sms.sgip.mo.server;

import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import com.nokia.sms.sgip.SgipConfig;
import com.nokia.sms.sgip.message.BindMessage;
import com.nokia.sms.sgip.message.BindResponseMessage;
import com.nokia.sms.sgip.message.DeliverMessage;
import com.nokia.sms.sgip.message.DeliverResponseMessage;
import com.nokia.sms.sgip.message.Head;
import com.nokia.sms.sgip.message.ReportMessage;
import com.nokia.sms.sgip.message.ReportResponseMessage;
import com.nokia.sms.sgip.message.UnBindMessage;
import com.nokia.sms.sgip.message.UnBindResponseMessage;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MOServerHandler extends IoHandlerAdapter {
    private CompositeConfiguration config = SgipConfig.getConfig();
    private Action deliverAction;
    private Action reportAction;

    public MOServerHandler() {
        String deliverActionClass = this.config.getString("sgip_mo_deliver_action_class");

        String reportActionClass = this.config.getString("sgip_mo_report_action_class");
        try {
            if ((deliverActionClass != null) && (!"".equals(deliverActionClass))) {
                Class<?> c1 = Class.forName(deliverActionClass);
                this.deliverAction = ((Action) c1.newInstance());
            }
            if ((reportActionClass != null) && (!"".equals(reportActionClass))) {
                Class<?> c2 = Class.forName(reportActionClass);
                this.reportAction = ((Action) c2.newInstance());
            }
        } catch (ClassNotFoundException e) {
            log.info("", e);
        } catch (InstantiationException e) {
            log.info("", e);
        } catch (IllegalAccessException e) {
            log.info("", e);
        }
        if (this.deliverAction != null) {
            log.info("DeliverActionClass=" + this.deliverAction.getClass());
        } else {
            log.warn("DeliverActionClass=null");
        }
        if (this.reportAction != null) {
            log.info("ReportActionClass=" + this.reportAction.getClass());
        } else {
            log.warn("ReportActionClass=null");
        }
    }

    public void exceptionCaught(IoSession session, Throwable cause)
            throws Exception {
        log.error("Remote:" + session.getRemoteAddress(), cause);
        session.closeOnFlush();
    }

    public void sessionOpened(IoSession session) {
        log.info("Remote:" + session.getRemoteAddress());
    }

    public void sessionClosed(IoSession session, IdleStatus status)
            throws Exception {
        log.info("Remote:" + session.getRemoteAddress());
    }

    public void messageSent(IoSession session, Object object)
            throws Exception {
    }

    public void messageReceived(IoSession session, Object object)
            throws Exception {
        if ((object instanceof BindMessage)) {
            BindMessage message = (BindMessage) object;
            byte operateResult = BindChecker.checkBindMessage(message);
            BindResponseMessage bindResp = new BindResponseMessage();
            Head head = new Head();
            head.setFlowId(message.getHead().getFlowId());
            bindResp.setHead(head);
            bindResp.setOperateResult(operateResult);
            session.write(bindResp);
            log.info("write:" + bindResp);
            if (operateResult != 0) {
                log.warn("CheckBindMessage fail!OperateResult=" + operateResult);
                CloseFuture closeFuture = session.closeOnFlush();
                closeFuture.awaitUninterruptibly();
                log.info("Session closed!" + (!session.isConnected()));
            }
        } else if ((object instanceof DeliverMessage)) {
            DeliverMessage message = (DeliverMessage) object;

            DeliverResponseMessage deliverResp = new DeliverResponseMessage();
            Head head = new Head();
            head.setFlowId(message.getHead().getFlowId());
            deliverResp.setHead(head);
            deliverResp.setOperateResult((byte) 0);
            session.write(deliverResp);
            if (this.deliverAction != null) {
                this.deliverAction.execute(message);
            }
        } else if ((object instanceof ReportMessage)) {
            ReportMessage message = (ReportMessage) object;

            ReportResponseMessage reportResp = new ReportResponseMessage();
            Head head = new Head();
            head.setFlowId(message.getHead().getFlowId());
            reportResp.setHead(head);
            reportResp.setOperateResult((byte) 0);
            session.write(reportResp);
            if (this.reportAction != null) {
                this.reportAction.execute(message);
            }
        } else if ((object instanceof UnBindMessage)) {
            UnBindMessage message = (UnBindMessage) object;

            UnBindResponseMessage unBindResp = new UnBindResponseMessage();
            Head head = new Head();
            head.setFlowId(message.getHead().getFlowId());
            unBindResp.setHead(head);
            session.write(unBindResp);

            CloseFuture closeFuture = session.closeOnFlush();
            closeFuture.awaitUninterruptibly();
            log.info("Session closed!" + (!session.isConnected()));
        }
    }

    public void sessionIdle(IoSession session, IdleStatus status)
            throws Exception {
        session.closeOnFlush();
        log.info("Closeing!");
    }
}
