package com.mercury.chat.server.protocol.group;

import static com.mercury.chat.common.constant.Constant.userInfo;
import static com.mercury.chat.common.util.Channels.get;
import static com.mercury.chat.common.util.Channels.has;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.ChannelMatcher;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.EventExecutor;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.mercury.chat.user.entity.User;

public class ChatChannelGroup extends DefaultChannelGroup {

	private CacheLoader<String,Channel> cacheLoader = new CacheLoader<String,Channel>(){
				@Override
				public Channel load(String key) throws Exception {
					return null;
				}
	};
	
	private RemovalListener<String,Channel> removalListener = new RemovalListener<String,Channel>(){

		@Override
		public void onRemoval(RemovalNotification<String, Channel> notification) {
			//XXX
		}
		
	};
	
	private LoadingCache<String,Channel> cache = CacheBuilder
												.newBuilder()
												.concurrencyLevel(4)
												.initialCapacity(8)
												.maximumSize(10000)
												.removalListener(removalListener)
												.recordStats()
												.build(cacheLoader);
	
	public LoadingCache<String,Channel> getCache(){
		return cache;
	}
	
	public ChatChannelGroup(EventExecutor executor) {
		super(executor);
	}

	public ChatChannelGroup(String name, EventExecutor executor) {
		super(name, executor);
	}

	@Override
	public boolean add(Channel channel) {
		boolean added = super.add(channel);
		if(has(channel,userInfo)){
			User user = get(channel,userInfo);
			cache.put(user.getUserId(), channel);
		}
		return added;
	}

	@Override
	public boolean remove(Object o) {
		Channel channel = null;
		if (o instanceof ChannelId) {
			ChannelId id = (ChannelId) o;
			channel = find(id);
		}else if(o instanceof Channel){
			channel = (Channel) o;
		}
		if(has(channel,userInfo)){
			User user = get(channel,userInfo);
			cache.invalidate(user.getUserId());
		}
		boolean removed = super.remove(o);
		return removed;
	}

	@Override
	public ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher) {
		return super.writeAndFlush(message, matcher);
	}

}

@@ -533,23 +533,16 @@
 he.Cache
-Builder
 ;%0D%0Aimpor
@@ -576,60 +576,15 @@
 ache
-Loader;%0D%0Aimport com.google.common.cache.LoadingCache
+Builder
 ;%0D%0Ai
@@ -796,200 +796,8 @@
 %0D%0A%0D%0A
-%09private CacheLoader%3CString,Channel%3E cacheLoader = new CacheLoader%3CString,Channel%3E()%7B%0D%0A%09%09%09%09@Override%0D%0A%09%09%09%09public Channel load(String key) throws Exception %7B%0D%0A%09%09%09%09%09return null;%0D%0A%09%09%09%09%7D%0D%0A%09%7D;%0D%0A%09%0D%0A
 %09pri
@@ -993,11 +993,54 @@
 %09%09//
-XXX
+TODO add logic to handler removing the channel
 %0D%0A%09%09
@@ -1063,23 +1063,16 @@
 private 
-Loading
 Cache%3CSt
@@ -1332,19 +1332,8 @@
 ild(
-cacheLoader
 );%0D%0A
@@ -1347,15 +1347,8 @@
 lic 
-Loading
 Cach

change the cache from loading cache to cache.