
package org.tio.sitexxx.im.server;

import org.lionsoul.ip2region.DataBlock;
import org.tio.core.ChannelContext;
import org.tio.core.intf.Packet;
import org.tio.monitor.RateLimiterWrap;
import org.tio.server.intf.TioServerListener;
import org.tio.sitexxx.im.common.CommandStat;
import org.tio.sitexxx.im.common.ImPacket;
import org.tio.sitexxx.im.common.ImSessionContext;
import org.tio.sitexxx.im.common.utils.ImUtils;
import org.tio.sitexxx.im.server.handler.wx.WxChatQueueApi;
import org.tio.sitexxx.service.ip2region.Ip2Region;
import org.tio.sitexxx.service.model.main.User;
import org.tio.sitexxx.service.model.main.WxSynItem;
import org.tio.sitexxx.service.service.chat.SynService;
import org.tio.sitexxx.service.vo.Const;
import org.tio.sitexxx.service.vo.Devicetype;
import org.tio.utils.jfinal.P;

import java.util.Date;
import java.util.Objects;

/**
 *
 * @author tanyaowu
 *
 */
public class TioSiteImTioServerListener implements TioServerListener {
	public static final TioSiteImTioServerListener	me			= new TioSiteImTioServerListener();

	/**
	 * @author tanyaowu
	 * 2016年12月16日 下午5:52:06
	 *
	 */
	private TioSiteImTioServerListener() {
	}

	@Override
	public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect) {
		ImSessionContext imSessionContext = new ImSessionContext();
		channelContext.setAttribute(Const.IM_SESSION_KEY, imSessionContext);

		int permitsPerSecond = P.getInt("request.permitsPerSecond");
		int warnClearInterval = 1000 * P.getInt("request.warnClearInterval");
		int maxWarnCount = P.getInt("request.maxWarnCount");
		int maxAllWarnCount = P.getInt("request.maxAllWarnCount");
		RateLimiterWrap rateLimiterWrap = new RateLimiterWrap(permitsPerSecond, warnClearInterval, maxWarnCount, maxAllWarnCount);

		imSessionContext.setRequestRateLimiter(rateLimiterWrap);

		if (isConnected) {
			String ip = channelContext.getClientNode().getIp();

			DataBlock dataBlock = Ip2Region.getDataBlock(ip);
			imSessionContext.setDataBlock(dataBlock);
		}
	}

	/**
	 * 
	 * @param channelContext
	 * @param packet
	 * @param packetSize
	 * @author: tanyaowu
	 */
	@Override
	public void onAfterDecoded(ChannelContext channelContext, Packet packet, int packetSize) {
		if (packet instanceof ImPacket) {
			ImPacket imPacket = (ImPacket) packet;
			CommandStat.getCommandStat(imPacket.getCommand()).received.incrementAndGet();
		}
	}

	/**
	 * 
	 * @param channelContext
	 * @param packet
	 * @param isSentSuccess
	 * @author: tanyaowu
	 */
	@Override
	public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess) {
		if (packet instanceof ImPacket) {
			ImPacket imPacket = (ImPacket) packet;
			if (isSentSuccess) {
				CommandStat.getCommandStat(imPacket.getCommand()).sent.incrementAndGet();
			}
		}
	}

	@Override
	public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) {
		User curr = ImUtils.getUser(channelContext);
		if (curr != null) {
			//如果该用户正在通话，则结束通话
			Devicetype devicetype = ImUtils.getDevicetype(channelContext);
			if (Objects.equals(devicetype.getValue(), Devicetype.IOS.getValue()) || Objects.equals(devicetype.getValue(), Devicetype.ANDROID.getValue())) {
				devicetype = Devicetype.APP;
			}
			WxChatQueueApi.leaveFocusQueue(curr, devicetype.getValue(), channelContext.getId());
			if (Objects.equals(devicetype.getValue(), Devicetype.APP.getValue()) || Objects.equals(devicetype.getValue(), Devicetype.H5.getValue())) {
				WxSynItem createItem = SynService.me.getSynItem(devicetype.getValue(), curr.getId(), Const.WxSynType.LINK_CREATE);
				if (createItem != null) {
					//添加同步记录
					SynService.me.insertSynTime(devicetype.getValue(), curr.getId(), Const.WxSynType.CHAT, new Date(), false);
				}
			}
		}
	}

	@Override
	public void onAfterHandled(ChannelContext channelContext, Packet packet, long cost) {
	}

	@Override
	public void onAfterReceivedBytes(ChannelContext channelContext, int receivedBytes) {
	}

	@Override
	public boolean onHeartbeatTimeout(ChannelContext channelContext, Long interval, int heartbeatTimeoutCount) {
		return false;
	}
}
