package com.sv.netty.netty;

import com.sv.netty.config.Constant;
import com.sv.netty.config.SpringContextHolder;
import com.sv.netty.service.MessageService;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * 服务器接受TCP协议数据处理器
 *
 * @author ranfi
 */

@ChannelHandler.Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {

    private static Logger logger = LoggerFactory.getLogger(ServerHandler.class);

    private MessageService messageService;

    public ServerHandler() {
        messageService = SpringContextHolder.getBean("messageService");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        super.channelRead(ctx, msg);
        String clientIp = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getClientIp();
        try {
            messageService.receive(ctx.channel(), msg.toString());
        }  catch (Exception e) {
            logger.error("[" + clientIp + "] host unknown error");
        }
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        logger.info("There is a client Registered. ip:" + clientIP);
        ctx.channel().attr(Constant.CHANNEL_PARAM).set(new ChannelParam(clientIP));
        messageService.online(ctx.channel());
    }


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }

    /**
     * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward
     * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
     * <p>
     * Sub-classes may override this method to change behavior.
     *
     * @param ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        logger.error("Client ip [" + clientIP + "] has inactive");
        Integer memberId = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getMemberId();
        String nickname = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getNickname();
        String machineSn = ctx.channel().attr(Constant.CHANNEL_PARAM).get().getDeviceSn();
        messageService.doOffLine(memberId, nickname,machineSn);
        messageService.destory(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        super.exceptionCaught(ctx, cause);
    }

    /**
     * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward
     * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
     * <p/>
     * Sub-classes may override this method to change behavior.
     *
     * @param ctx
     * @param evt
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent event = (IdleStateEvent) evt;
        // 如果Channel读取数据闲置，则关闭连接
//        if (event.state() == IdleState.READER_IDLE) {
//            String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
//            logger.info("Client [" + clientIP + "] has idle");
//            messageService.destory(ctx.channel());
//            ctx.channel().close();
//        }
    }

}
