package com.fr.tx.common.netty.wbs;

import javax.swing.JTextArea;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.fr.tx.common.data.CacheData;
import com.fr.tx.common.util.ConvertUtil;
import com.fr.tx.common.util.StringUtil;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * ClassName:MyWebSocketServerHandler Function:
 * 
 * @author hxy
 */
public class MyWebSocketServerHandler extends SimpleChannelInboundHandler<Object> {

	private static final Logger logger = Logger.getLogger(MyWebSocketServerHandler.class);

	private WebSocketServerHandshaker handshaker;

	private JTextArea jta;

	/**
	 * 变电所名
	 */
	private String mBds = "";

	public MyWebSocketServerHandler(JTextArea jta) {
		this.jta = jta;
	}

	/**
	 * channel 通道 action 活跃的
	 * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("建立连接" + ctx.channel().remoteAddress().toString());
	}

	/**
	 * channel 通道 Inactive 不活跃的
	 * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端关闭了通信通道并且不可以传输数据
	 */
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		if(StringUtil.isNotEmpty(mBds)){
			CacheData.sessionWebMap.get(mBds).remove(ctx.channel());
		}
		// 通道关闭，移除map中的 ChannelGroup 的对象
		System.out.println( "关闭连接" + ctx.channel().remoteAddress().toString());
	}

	/**
	 * 接收客户端发送的消息 channel 通道 Read 读
	 * 简而言之就是从通道中读取数据，也就是服务端接收客户端发来的数据。但是这个数据在不进行解码时它是ByteBuf类型的
	 */
	protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
		// 传统的HTTP接入
		if (msg instanceof FullHttpRequest) {
			handleHttpRequest(ctx, ((FullHttpRequest) msg));
		} else if (msg instanceof TextWebSocketFrame) {
			TextWebSocketFrame text = (TextWebSocketFrame) msg;
			String sendText = text.text();
			// 哪个站发过来的发给哪个中心
			logger.info("接收到客户数据：" + sendText);
			handleWebSocket(ctx, sendText);
		}

	}

	/**
	 * channel 通道 Read 读取 Complete 完成 在通道读取完成后会在这个方法里通知，对应可以做刷新操作 ctx.flush()
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	/**
	 * webSocket数据分析
	 * 
	 * @param ctx
	 * @param sendText
	 */
	@SuppressWarnings("unused")
	private void handleWebSocket(ChannelHandlerContext ctx, String sendText) {
		JSONObject jsStr = JSONObject.parseObject(sendText);
		String action = jsStr.get("action").toString();
		mBds = jsStr.get("bds").toString();
		String response = "";
		Channel channel = null;
		// 判断客户端访问的变电所是否注册了的
		if (CacheData.sessionBds.contains(mBds)) {
			// 注册了的把channel放到ChannelGroup中去
			// 已经有ChannelGroup
			if (CacheData.sessionWebMap.containsKey(mBds)) {
				CacheData.sessionWebMap.get(mBds).add(ctx.channel());
			} else {
				// 没有ChannelGroup new
				ChannelGroup cg = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
				cg.add(ctx.channel());
				CacheData.sessionWebMap.put(mBds, cg);
			}
		} else {
			mBds = "";
			response = "{\"ret\":-1,\"msg\":\"连接不合法！\"}";
			ctx.channel().writeAndFlush(new TextWebSocketFrame(response));
			ctx.channel().close();
			return;
		}
		String addr = "";
		response = "{\"ret\":0,\"msg\":\"连接成功\"}";
		ctx.channel().writeAndFlush(new TextWebSocketFrame(response));
	}

	@SuppressWarnings("deprecation")
	private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
		// 如果HTTP解码失败，返回HHTP异常
		if (!req.getDecoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
			sendHttpResponse(ctx, req,
					new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
			return;
		}
		String uri = req.getUri();
		// 构造握手响应返回，本机测试
		WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
				"ws://" + req.headers().get(HttpHeaders.Names.HOST) + uri, null, false);
		handshaker = wsFactory.newHandshaker(req);
		if (handshaker == null) {
			WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
		} else {
			handshaker.handshake(ctx.channel(), req);
		}

	}

	/**
	 * 回复数据
	 * 
	 * @param ctx
	 * @param req
	 * @param res
	 */
	@SuppressWarnings("deprecation")
	private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse res) {
		logger.info("sendHttpResponse");
		// 返回应答给客户端
		if (res.getStatus().code() != 200) {
			ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8);
			res.content().writeBytes(buf);
			buf.release();
		}
		// 如果是非Keep-Alive，关闭连接
		ChannelFuture f = ctx.channel().writeAndFlush(res);
		if (!HttpHeaders.isKeepAlive(req) || res.getStatus().code() != 200) {
			f.addListener(ChannelFutureListener.CLOSE);
		}
	}

	/**
	 * exception 异常 Caught 抓住 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();
	}
}