package com.hammurapi.common;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.hammurapi.extract.Predicate;

/**
 * Context delegating to other contexts "parts".
 * @author Pavel Vlasov
 *
 */
public class CompositeContext implements MutableContext {
	
	private Context[] parts;
	
	public CompositeContext() {
		// 
	}

	public CompositeContext(Context...parts) {
		this.parts = parts;
	}
	
	public void setParts(Context...parts) {
		this.parts = parts;
	}
	
	public <T> Iterator<T> lookupAll(Class<T> serviceClass, Predicate<T, Context>... selectors) {
		List<T> all = new ArrayList<T>();
		for (Context part: parts) {
			if (part!=null) {
				Iterator<T> cit = part.lookupAll(serviceClass, selectors);
				while (cit.hasNext()) {
					all.add(cit.next());
				}
			}
		}
		return all.iterator();
	}
	
	public <T> T lookup(Class<T> serviceClass, Predicate<T, Context>... selectors) {
		for (Context part: parts) {
			if (part!=null) {
				T ret = part.lookup(serviceClass, selectors);
				if (ret!=null) {
					return ret;
				}
			}
		}
		return null;
	}
	
	public Object lookup(String name) {
		for (Context part: parts) {
			if (part!=null) {
				Object ret = part.lookup(name);
				if (ret!=null) {
					return ret;
				}
			}
		}
		return null;
	}

	public void bind(String name, Object obj) {
		for (Context part: parts) {
			if (part instanceof MutableContext) {
				((MutableContext) part).bind(name, obj);
				return;
			}
		}
		throw new IllegalStateException("Composite context doesn't contain mutable parts.");
	}

	public <T> void register(Class<? super T> type, T service) {
		for (Context part: parts) {
			if (part instanceof MutableContext) {
				((MutableContext) part).register(type, service);
				return;
			}
		}
		throw new IllegalStateException("Composite context doesn't contain mutable parts.");
	}

	public Object unbind(String name) {
		for (Context part: parts) {
			if (part instanceof MutableContext) {
				return ((MutableContext) part).unbind(name);
			}
		}
		throw new IllegalStateException("Composite context doesn't contain mutable parts.");
	}

	public <T> void unregister(Class<? super T> type, T service) {
		for (Context part: parts) {
			if (part instanceof MutableContext) {
				((MutableContext) part).unregister(type, service);
				return;
			}
		}
		throw new IllegalStateException("Composite context doesn't contain mutable parts.");
	}
}
	
