package com.tandbergtv.watchpoint.pmm.title.conf;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

/**
 * Manager class for all PMM Title specifications. 
 * 
 * @author Raj Prakash
 */
public class SpecificationManager implements ISpecificationManager {
	private static final Logger logger = Logger.getLogger(SpecificationManager.class);
	private static final String SERVICE_NAME = "Specification Manager";
	
	private boolean started = false;
	private Collection<Specification> specs = new ArrayList<Specification>();
	
	
	/**
	 * Hiding the constructor to support Singleton
	 */
	private SpecificationManager() {
	}
	
	/**
	 * Returns a new instance of the specification manager
	 * 
	 * @param factory
	 * @return
	 */
	public static SpecificationManager newInstance() {
		return new SpecificationManager();
	}
	
	/**
	 * Gets the service name.
	 */
	public String getServiceName() {
		return SERVICE_NAME;
	}

	/**
	 * Starts the Manager
	 */
	public synchronized void start() {
		if(started)
			return;

		started = true;
		logger.info("Successfully started the Specification Manager.");
	}
	
	/**
	 * Shuts down the Manager.
	 */
	public synchronized void stop() {
		specs = new HashSet<Specification>();
		started = false;
	}
	
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager#getAllSpecifications()
	 */
	public Collection<Specification> getAllSpecifications() {
		return specs;
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager#getSpecificationByName(java.lang.String)
	 */
	public Specification getSpecificationByName(String name) {
		for(Specification s : specs)
			if(s.getName().equals(name))
				return s;
		return null;
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager#addSpecification(com.tandbergtv.watchpoint.pmm.title.conf.Specification)
	 */
	public void addSpecification(Specification specification) {
		this.specs.add(specification);
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager#getJobRuleMenuOptions()
	 */
	public Map<String, Set<String>> getJobRuleMenuOptions() {
		Map<String, Set<String>> allJobRuleMenuOptions = new HashMap<String, Set<String>>();
		for(Specification s : specs) {
			allJobRuleMenuOptions.put(s.getName(), getMenuOptionNames(s.getJobRuleMenuOptions()));
		}
		return allJobRuleMenuOptions; 
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager#getJobParameterMenuOptions()
	 */
	public Map<String, Set<String>> getJobParameterMenuOptions() {
		Map<String, Set<String>> allJobParameterMenuOptions = new HashMap<String, Set<String>>();
		for(Specification s : specs) {
			allJobParameterMenuOptions.put(s.getName(),
					getMenuOptionNames(s.getJobParameterMenuOptions()));
		}
		return allJobParameterMenuOptions; 
	}

	/**
	 * Gets the name of menu options as a set of string objects.
	 * Returns an empty set when input argument menuOptions is null or empty.
	 */
	private Set<String> getMenuOptionNames(List<MenuOption> menuOptions) {
		Set<String> menuOptionNames = new HashSet<String>();
		if(menuOptions != null) {
			for(MenuOption mo : menuOptions) {
				menuOptionNames.add(mo.getName());
			}
		}
		return menuOptionNames;
	}
}
