/**
 * GeneralReferenceEvaluator.java
 * Created on Aug 12, 2008
 * (C) Copyright TANDBERG Television Ltd.
 */
package com.tandbergtv.watchpoint.pmm.job.referenceEvaluator;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.tandbergtv.watchpoint.pmm.entities.JobParameter;
import com.tandbergtv.watchpoint.pmm.job.util.JobScheduleInfoConstants;
import com.tandbergtv.watchpoint.pmm.job.util.ParameterReferenceHelper;

/**
 * This class resolves any parameter references for the 'General' group shown in the drop down to
 * select parameter references for job parameters. It expects a JobData type of object and uses the
 * info from that to substitute values.
 * 
 * @author spuranik
 * 
 */
public class GeneralReferenceEvaluator extends ReferenceEvaluator {

	private Logger logger = Logger.getLogger(GeneralReferenceEvaluator.class);

	// name of the group under which the item will be listed in the drop down.
	private String GENERAL_PARAMETER_REFERENCE_GROUP = "General";

	// format in which the job execution format will be converted before
	// being subsititued at the time of evaluation.
	private String JOB_EXECUTION_DATE_FORMAT = "yyyy-MM-dd";

	// fields that are listed under the 'General' group of the job parameters drop down menu
	private static String JOBEXECUTION_DATE = "Job Execution Date";

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.tandbergtv.watchpoint.pmm.job.referenceEvaluator.ReferenceEvaluator#evaluate(java.lang.Object,
	 *      java.util.Map)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void evaluate(Object entity, Map<String, Object> info) {
		// if the entity which will be used to resolve the references is not of type JobData
		// move on to the next evalutor.
		if (entity.getClass() == JobData.class) {
			JobData data = (JobData) entity;
			// if there are any references of 'General' type only then, try to resolve it
			List<JobParameter> jobParameters = (List<JobParameter>) info
					.get(JobScheduleInfoConstants.JOB_PARAMETERS);
			// resolve any 'General' references using the info in the entity sent.
			substituteValues(jobParameters, data);
		}

		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) {
		// 'General' category currently does not expect any rule parameters for which the path needs
		// to be evaluated hence just forwarding the request to the next one if any else returns
		// null.
		if (this.successor != null) {
			return successor.getPath(property);
		}

		return null;
	}

	/**
	 * this method goes thru the job parameter list and looks for parameter references of General
	 * type and substitutes them with the appropriate values from the data object passed along
	 * 
	 * @param jobParameters
	 *            list of job params to be evaluated
	 * @param jobData
	 *            data object which has the values that will be substituted in the list.
	 */
	private void substituteValues(List<JobParameter> jobParameters, JobData data) {

		for (JobParameter parameter : jobParameters) {
			try {
				String parameterReference = parameter.getValue();
				if (ParameterReferenceHelper.isParameterReference(parameterReference)) {
					String groupName = ParameterReferenceHelper.getGroupName(parameterReference);
					if (groupName.equalsIgnoreCase(GENERAL_PARAMETER_REFERENCE_GROUP)) {
						// break up the string to get the property name
						String property = ParameterReferenceHelper
								.getPropertyName(parameterReference);

						// if the job execution date property was selected as a parameter reference
						if (property.equalsIgnoreCase(JOBEXECUTION_DATE)) {
							String date = formatDate(data.getJobExecutionDate(),
									JOB_EXECUTION_DATE_FORMAT);
							parameter.setValue(date);
						}
					}
				}
			} catch (RuntimeException e) {
				// if there is a problem with one property, move on to the next one.
				logger.warn("Error while subsituting value for: " + parameter.getValue(), e);
			}
		}
	}

	/**
	 * converts the given date to the destination format
	 * 
	 * @param dateToFormat
	 *            date to be converted
	 * @return string representation of the converted date.
	 */
	private String formatDate(Date dateToFormat, String toFormat) {
		if (dateToFormat == null) {
			throw new RuntimeException("Date is null.");
		}

		SimpleDateFormat from = new SimpleDateFormat();
		Calendar c = Calendar.getInstance();
		c.setTime(dateToFormat);
		from.setCalendar(c);
		SimpleDateFormat to = new SimpleDateFormat(toFormat);
		return to.format(dateToFormat);
	}
}
