package com.yonge.netty.server.handler.message;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;

import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.yonge.netty.server.handler.ChannelContextConstants;
import com.yonge.netty.server.handler.NettyChannelManager;

@Component
@ChannelHandler.Sharable
public class BinaryWebSocketFrameHandler extends SimpleChannelInboundHandler<BinaryWebSocketFrame> implements ApplicationContextAware,InitializingBean {

	private final static Logger LOGGER = LoggerFactory.getLogger(BinaryWebSocketFrameHandler.class);
	
	@Autowired
	private NettyChannelManager nettyChannelManager;

	private ApplicationContext applicationContext;
	
	private Map<String, MessageHandler> handlerMap;

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame frame) throws Exception {

		Channel channel = ctx.channel();

		ByteBuf buf = frame.content().retain();

		try {
			byte[] datas = ByteBufUtil.getBytes(buf);

			String user = nettyChannelManager.getUser(channel);
			
			String action = channel.attr(ChannelContextConstants.CHANNEL_ATTR_KEY_ACTION).get();
			
			if(handlerMap == null){
				LOGGER.error("消息处理器没有初始化");
			}
			MessageHandler handler = handlerMap.get(action);
			
			if(handler != null){
				handler.handleBinaryMessage(user, channel, datas);
			}
			
		} finally {
			buf.release();
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		handlerMap = applicationContext.getBeansOfType(MessageHandler.class).values().stream()
				.collect(Collectors.toMap(MessageHandler::getAction, t -> t));
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
