package chat.module;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import chat.module.entity.FriendShip;
import frame.util.ContentBuilder;

public class ConcurrentMapList<T> implements Iterable<T> {

	protected List<T> itemList;
	protected Map<String, T> itemMap;
	protected Map<String, Integer> indexMap;
	
	
	public ConcurrentMapList() {
		itemList = new ArrayList<T>();
		itemMap = new HashMap<String, T>();
	}
	
	public void addAll(Map<String, T> map) {
		synchronized (this) {
			Set<String> keys = map.keySet();
			
			for (String key: keys) {
				add(key, map.get(key));
			}
		}
	}
	
	public void add(String key, T item) {
		if (key == null) {
			return;
		}
		
		synchronized (this) {
			key = key.toLowerCase();
			itemMap.put(key, item);
			itemList.add(item);
		}
	}
	
	public void addMapList(String key, T items) {
		if (key == null) {
			return;
		}
		synchronized (this) {
			key = key.toLowerCase();
			itemMap.put(key, items);
		}
	}

	public void set(String key, T item) {
		if (key == null) {
			return;
		}
		
		synchronized (this) {
			if (indexMap == null) {
				indexMap = new HashMap<String, Integer>();
			}
			
			key = key.toLowerCase();
			
			if (!itemMap.containsKey(key)) {
				itemMap.put(key, item);
				indexMap.put(key, itemList.size());
				itemList.add(item);
			}
			else {
				Integer idx = indexMap.get(key);
				itemList.set(idx, item);
			}
		}
	}
	
	public T get(String key) {
		if (key == null) {
			return null;
		}
		
		synchronized (this) {
			key = key.toLowerCase();
			return itemMap.get(key);
		}
	}
	
	public T get(int idx) {
		synchronized (this) {
			return itemList.get(idx);
		}
	}
	
	public T delete(String key) {
		if (key == null) {
			return null;
		}
		
		synchronized (this) {
			T obj = itemMap.get(key.toLowerCase());
			
			if (obj != null) {
				itemMap.remove(key);
				itemList.remove(obj);
			}
			
			return obj;
		}
	}
	
	public List<T> getList() {
		synchronized (this) {
			return itemList;
		}
	}
	
	public Set<String> getKeySet() {
		synchronized (this) {
			return itemMap.keySet();
		}
	}	

	public boolean isEmpty() {
		return itemList.isEmpty();
	}
	
	public int size() {
		return itemList.size();
	}
	
	public int mapSize() {
		return itemMap.size();
	}
	
	public Iterator<T> iterator() {
		synchronized (this) {
			return itemList.iterator();
		}
	}

	public void clear() {
		itemList.clear();
		itemMap.clear();
	}
	
	public String toString(String separator) {
		ContentBuilder builder = new ContentBuilder(separator);
		
		for (String key: itemMap.keySet()) {
			builder.append(key);
		}
		
		return builder.toString();
	}
	
	public Set<String> keySet() {
		return itemMap.keySet();
	}

	public boolean equals(ConcurrentMapList<T> another) {
		if (another == null) {
			return false;
		}
		
		if (this == another) {
			return true;
		}
		
		Set<String> keys = itemMap.keySet();
		for (String key: keys) {
			if (!another.contains(key)) {
				return false;
			}
		}
		
		Set<String> anotherKeys = another.itemMap.keySet();
		for (String anotherKey: anotherKeys) {
			if (!contains(anotherKey)) {
				return false;
			}
		}
		
		return true;
	}

	public boolean contains(String key) {
		if (key == null) {
			return false;
		}
		
		synchronized (this) {
			key = key.toLowerCase();
			return itemMap.containsKey(key);
		}
	}

	public Object[] toArray() {
		return itemList.toArray();
	}

	@SuppressWarnings("hiding")
	public <T> T[] toArray(T[] a) {
		return itemList.toArray(a);
	}

}