package com.sagacloud.endpoints.tagset;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

/**
 * 对象与业务标签关系缓存 
 */
public class ObjectTagCache {
	/** {标签编码：[对象id]} */
	private static Map<String, ConcurrentSkipListSet<String>> tagHasObjs = new ConcurrentHashMap<>();
	/** {对象id：[标签编码]} */
	private static Map<String, ConcurrentSkipListSet<String>> objHasTags = new ConcurrentHashMap<>();
	public static void cleanCache() {
		tagHasObjs.clear();
		objHasTags.clear();
	}
	/**
	 * 获取具有标签的对象id集合
	 * @return
	 */
	public static Set<String> getObjsThatHasTag() {
		return objHasTags.keySet();
	}
	/**
	 * 获取对象具有的标签
	 * @param objId
	 * @return
	 */
	public static Set<String> getTagsByObjId(String objId) {
		return objHasTags.get(objId) == null?new HashSet<String>():objHasTags.get(objId);
	}
	/**
	 * 向缓存集合{标签编码：[对象id]}和{对象id：[标签编码]}中添加对象id与标签编码关系信息
	 * @param tag_objs {标签编码：[对象id]}
	 */
	public static void addTagAndObjs(Map<String, Set<String>> tag_objs) {
		cacheAdd(tag_objs, tagHasObjs, objHasTags);
	}
	/**
	 * 向缓存集合{标签编码：[对象id]}和{对象id：[标签编码]}中添加对象id与标签编码关系信息
	 * @param tag_objs {对象id：[标签编码]}
	 */
	public static void addObjAndTags(Map<String, Set<String>> obj_tags) {
		cacheAdd(obj_tags, objHasTags, tagHasObjs);
	}
	private static void cacheAdd(Map<String, Set<String>> key_value, 
			Map<String, ConcurrentSkipListSet<String>> collection1, Map<String, ConcurrentSkipListSet<String>> collection2) {
		if(key_value == null) {
			return;
		}
		for(String objId : key_value.keySet()) {
			Set<String> tags = key_value.get(objId);
			if(collection1.containsKey(objId)) {
				if(tags != null) {
					collection1.get(objId).addAll(tags);
				}
			}else {
				ConcurrentSkipListSet<String> objsSet = new ConcurrentSkipListSet<>();
				if(null!=tags) {
					objsSet.addAll(tags);
				}
				collection1.put(objId, objsSet);
			}
			
			if(null != tags && !tags.isEmpty()) {
				for(String tag : tags) {
					if(collection2.containsKey(tag)) {
						collection2.get(tag).add(objId);
					}else {
						collection2.put(tag, new ConcurrentSkipListSet<>(Arrays.asList(objId)));
					}
				}
			}
		}
	}

	/**
	 * 从缓存集合{标签编码：[对象id]}和{对象id：[标签编码]}移除某些对象id与标签关系信息
	 * @param tags
	 * @param objs
	 */
	public static void delObjInTag(Set<String> tags, Set<String> objs) {
		if(null == tags || objs == null || tags.isEmpty() || objs.isEmpty()) {
			return;
		}
		for(String tag : tags) {
			if(tagHasObjs.containsKey(tag)) {
				tagHasObjs.get(tag).removeAll(objs);
			}
		}
		for(String objId : objs) {
			if(objHasTags.containsKey(objId)) {
				objHasTags.get(objId).removeAll(tags);
			}
		}
	}
	
	/**
	 * 从缓存集合{标签编码：[对象id]}和{对象id：[标签编码]}移除某些对象id与标签关系信息
	 * @param tag
	 * @param objs
	 */
	public static void delObjInTag(String tag, Set<String> objs) {
		if(null == tag) {
			return;
		}
		delObjInTag(new HashSet<String>(Arrays.asList(tag)), objs);
	}
	
	/**
	 * 从缓存集合{标签编码：[对象id]}和{对象id：[标签编码]}移除某些对象id与标签关系信息
	 * @param tags
	 * @param obj
	 */
	public static void delObjInTag(Set<String> tags, String obj) {
		if(null == obj) {
			return;
		}
		delObjInTag(tags, new HashSet<String>(Arrays.asList(obj)));
	}
	
	/**
	 * 判断对象是否有指定标签若objId为null或shouldHasTags为null返回true
	 * @param objId 对象id
	 * @param shouldHasTags 应该具有的标签集合
	 * @param hasAll true全部都有，false有一个就可以
	 * @return
	 */
	public static boolean ifHasTag(String objId, Set<String> shouldHasTags, boolean hasAll) {
		if(null != objId && null != shouldHasTags) {
			if(shouldHasTags.isEmpty()) {
				return true;
			}
			if(hasAll) {
				return null != getTagsByObjId(objId) ? getTagsByObjId(objId).containsAll(shouldHasTags) : false;
			}else {
				if(null == getTagsByObjId(objId)) {
					return false;
				}
				
				boolean realHas = false;
				for(String tag : shouldHasTags) {
					if(getTagsByObjId(objId).contains(tag)) {
						realHas = true;
						break;
					}
				}
				return realHas;
			}
		}
		return true;
	}
}
