/**
 * TitleReferenceEvaluator.java
 * Created on Jun 3, 2008
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.watchpoint.pmm.job.referenceEvaluator;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.tandbergtv.watchpoint.pmm.entities.IContainer;
import com.tandbergtv.watchpoint.pmm.entities.JobParameter;
import com.tandbergtv.watchpoint.pmm.entities.Title;
import com.tandbergtv.watchpoint.pmm.job.callback.CallbackHelper;
import com.tandbergtv.watchpoint.pmm.job.util.JobScheduleInfoConstants;
import com.tandbergtv.watchpoint.pmm.job.util.ParameterReferenceHelper;
import com.tandbergtv.watchpoint.pmm.title.ITitleService;
import com.tandbergtv.watchpoint.pmm.title.conf.ISpecificationManager;
import com.tandbergtv.watchpoint.pmm.title.conf.MenuOption;
import com.tandbergtv.watchpoint.pmm.title.conf.Specification;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleProvider;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleProviderRegistry;
import com.tandbergtv.workflow.core.service.ServiceRegistry;

/**
 * @author spuranik
 * 
 */
public class TitleReferenceEvaluator extends ReferenceEvaluator {

	private Logger logger = Logger.getLogger(TitleReferenceEvaluator.class);
	private static String TITLE_PARAMETER_REFERENCE_GROUP = "Title";
	private static String TITLE_ID = "Id";
	private static String TITLE_NAME = "Name";
	private static String TITLE_SOURCE_PATH = "External Source Path";

	private ITitleService titleService;
	private ISpecificationManager specMgr;

	/**
	 * @return the titleService
	 */
	public ITitleService getTitleService() {
		return titleService;
	}

	/**
	 * @param titleService
	 *            the titleService to set
	 */
	public void setTitleService(ITitleService titleService) {
		this.titleService = titleService;
	}

	/**
	 * @return the specMgr
	 */
	public ISpecificationManager getSpecMgr() {
		return specMgr;
	}

	/**
	 * @param specMgr
	 *            the specMgr to set
	 */
	public void setSpecMgr(ISpecificationManager specMgr) {
		this.specMgr = specMgr;
	}

	public TitleReferenceEvaluator(ITitleService titleService, ISpecificationManager specMgr) {
		this.titleService = titleService;
		this.specMgr = specMgr;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tandbergtv.watchpoint.pmm.job.referenceEvaluator.ReferenceEvaluator#evaluate(java.lang.Object,
	 *      java.util.Map)
	 */
	@Override
	@SuppressWarnings("unchecked")
	@Deprecated
	public void evaluate(Object entity, Map<String, Object> info) {
		/*
		logger.debug("Evaluating Title parameter references");

		// check if the recvd entity is a title, it could be a schedule!
		if (entity != null && entity.getClass().equals(Title.class)) {
			Title title = (Title) entity;

			List<JobParameter> paramters = (List<JobParameter>) info
					.get(JobScheduleInfoConstants.JOB_PARAMETERS);
			for (JobParameter parameter : paramters) {
				try {
					String parameterReference = parameter.getValue();
					if (ParameterReferenceHelper.isParameterReference(parameterReference)) {
						String groupName = ParameterReferenceHelper
								.getGroupName(parameterReference);
						// the group name could be a combination of 2 level groups, hence cannot
						// check for title directly
						if (groupName.startsWith(TITLE_PARAMETER_REFERENCE_GROUP)) {

							String leafGroupName = ParameterReferenceHelper.getLeafGroup(groupName);
							String propertyName = ParameterReferenceHelper
									.getPropertyName(parameterReference);

							// if there is no spec then the leaf group is the same as the group
							// name
							if (leafGroupName.equals(groupName)) {
								// this is a spec independent property e.g. id and name of title
								ParameterReferencePath path = new ParameterReferencePath();
								path.setParameterReference(parameterReference);

								if (propertyName.equalsIgnoreCase(TITLE_ID)) {
									parameter.setValue(Long.valueOf(title.getId()).toString());
								} else if (propertyName.equalsIgnoreCase(TITLE_NAME)) {
									parameter.setValue(title.getName());
								} else if (propertyName.equalsIgnoreCase(TITLE_SOURCE_PATH)) {

									String titleExternalLocation = title.getExternalLocation();
									ServiceRegistry registry = ServiceRegistry.getDefault();
									ITitleProviderRegistry titleProviderRegistry = registry
											.lookup(ITitleProviderRegistry.class);
									ITitleProvider provider = titleProviderRegistry
											.getProviderForTitle(titleExternalLocation);
									if (provider != null) {
										String externalPath = provider
												.getProviderInstanceURL(titleExternalLocation);
										parameter.setValue(externalPath);
									} else {
										logger.info("Provider for title: " + title.getId()
												+ " is null.");
										parameter.setValue(null);
									}
								}
							} else {
								// spec dependent property evaluation will be done by title
								// service. Make sure that the spec matches before evaluating.
								if (leafGroupName.equals(title.getSpecification())) {
									String propertyValue = titleService
											.evaluateJobParameterMenuOption(title, propertyName);
									parameter.setValue(propertyValue);
								} else {
									logger.warn("Title: " + title.getId() + " is not of "
											+ leafGroupName
											+ " spec. So not evaluating the value for property: "
											+ parameterReference);
								}
							}
						}
					}
				} catch (RuntimeException e) {
					// if there is a problem with one property, move on to the next.
					IContainer container = CallbackHelper.getContainer(info);
					String errorMsg = "Job execution failed for job: "
						+ info.get(JobScheduleInfoConstants.JOB_NAME) + " ["
						+ container.getContainerType() + ":" + container.getContainerName() + "]"
						+ " Error while trying to evaluate title reference";
				logger.warn(errorMsg, e);
				}
			}
		}

		if (successor != null) {
			successor.evaluate(entity, info);
		}
		*/
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tandbergtv.watchpoint.pmm.job.referenceEvaluator.ReferenceEvaluator#getPath(java.lang.String)
	 */
	@Override
	public ParameterReferencePath getPath(String property) {

		// first make sure that the property is a parameter reference
		// then does it refer to a title parameter reference
		// if yes, get the path for this property
		// else forward the request to the next one in the chain if any or else return null

		try {
			if (ParameterReferenceHelper.isParameterReference(property)) {
				String groupName = ParameterReferenceHelper.getGroupName(property);
				if (groupName.startsWith(TITLE_PARAMETER_REFERENCE_GROUP)) {
					// title references will always have Title Prefixed to the spec.
					String specName = ParameterReferenceHelper.getLeafGroup(groupName);
					String propertyName = ParameterReferenceHelper.getPropertyName(property);

					Specification spec = specMgr.getSpecificationByName(specName);
					if (spec == null) {
						throw new RuntimeException("Specification: " + specName
								+ " not found for property: " + propertyName);
					}

					MenuOption option = spec.getJobRuleMenuOption(propertyName);

					boolean isMetadata = option.isMetadata();
					String optionPropertyName = isMetadata ? option.getMetadataProperty() : option
							.getProperty();

					ParameterReferencePath path = new ParameterReferencePath();
					path.setName(option.getTitleName());
					path.setParameterReference(property);
					path.setPropertyName(optionPropertyName);
					path.setMetadata(isMetadata);

					return path;
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("Error while getting path for: " + property, e);
		}

		if (successor != null) {
			return successor.getPath(property);
		}
		return null;
	}
}
