package com.tandbergtv.watchpoint.pmm.entities;

import java.util.List;

import org.apache.log4j.Logger;

import com.tandbergtv.workflow.core.ProcessPriority;

/**
 * This class represents the job instance created for a partner/service
 *  
 * @author spuranik
 */
public class Job {
	// id for all jobs not yet in db
	public static final int DEFAULT_ID = 0;
	private static final int HASHCODE_MULTIPLICATION_FACTOR = 5;
	private static final int HASHCODE_ADDITION_FACTOR = 101;
	private Logger logger = Logger.getLogger(Job.class);

	// job id in db
	private long id;

	// job name provided by user
	private String name;

	// partner/service context, this job is associated with
	private Context context;

	// will be used as the work order priority
	private ProcessPriority priority;

	// template name (- version) associated with this job
	private String templateName;

	// all params part of the template
	private List<JobParameter> jobParams;

	// Rule instance associated with this job.
	private Rule rule;

	/**
	 * Default ctor
	 */
	public Job() {

	}

	/**
	 * @param id
	 *            to be set as jobId
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * @return jobId
	 */
	public long getId() {
		return id;
	}

	/**
	 * @return job name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            to be set as job name
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return context id for this job
	 */
	public Context getContext() {
		return context;
	}

	/**
	 * @param contextId
	 *            to be set as this job's contextid
	 */
	public void setContext(Context context) {
		this.context = context;
	}

	/**
	 * @return priority for this job
	 */
	public ProcessPriority getPriority() {
		return priority;
	}

	/**
	 * @param priority
	 *            to be set for job
	 */
	public void setPriority(ProcessPriority priority) {
		this.priority = priority;
	}

	/**
	 * @return template name for this job
	 */
	public String getTemplateName() {
		return templateName;
	}

	/**
	 * @param templateName
	 *            to be set as job's template
	 */
	public void setTemplateName(String templateName) {
		this.templateName = templateName;
	}

	/**
	 * @return list of job params for this job
	 */
	public List<JobParameter> getJobParams() {
		return jobParams;
	}

	/**
	 * @param jobParams
	 *            for this job
	 */
	public void setJobParams(List<JobParameter> jobParams) {
		this.jobParams = jobParams;
	}

	/**
	 * @return rule for this job
	 */
	public Rule getRule() {
		return rule;
	}

	/**
	 * @param rule
	 *            to be set for this job
	 */
	public void setRule(Rule rule) {
		this.rule = rule;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Job) {
			Job jobObj = (Job) obj;

			if (jobObj.getId() != DEFAULT_ID && this.getId() != DEFAULT_ID) {
				return (jobObj.getId() == this.getId());
			} else {
				return super.equals(obj);
			}
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		long hash = this.id * HASHCODE_MULTIPLICATION_FACTOR + HASHCODE_ADDITION_FACTOR;
		int hashCode = new Long(hash).hashCode();
		if (this.id == DEFAULT_ID) {
			hashCode = super.hashCode();
		}
		return hashCode;
	}

	/**
	 * @return
	 * 	true/false based on whether the rule for this job is associated
	 *  with titles or not.
	 */
	public boolean isTitleAssociated() {
		return this.getRule().getType().getTitlesAssociated();
	}

	/**
	 * @return
	 * 	 a string representing the rule type including the rule values given by the user 
	 */
	public String getScheduleRuleString() {
		Rule rule = getRule();
		String selectedRuletypeName = rule.getType().getName();

		try {
			// title/schedule meta data based rule 
			if (selectedRuletypeName.equals(JobRuleTypeConstants.METADATA_BASED_RULE)) {
				List<RuleParameter> ruleParams = rule.getParams();
				StringBuilder sb = new StringBuilder();

				sb.append(ruleParams.get(JobRuleTypeConstants.NUMBER_OF_DAYS_INDEX).getValue());
				sb.append(" day(s) ");
				sb.append(ruleParams.get(JobRuleTypeConstants.TIMEFRAME_INDEX).getValue());
				sb.append(" ");
				sb.append(ruleParams.get(JobRuleTypeConstants.METADATA_INDEX).getValue());
				sb.append(" at ");
				sb.append(ruleParams.get(JobRuleTypeConstants.TIME_INDEX).getValue());

				return sb.toString();
			} else if (selectedRuletypeName.equals(JobRuleTypeConstants.EVERY_N_DAYS_RULE)) {
				List<RuleParameter> ruleParams = rule.getParams();

				StringBuilder sb = new StringBuilder();
				sb.append("Every ");
				sb.append(ruleParams.get(JobRuleTypeConstants.DAYS_INDEX).getValue());
				sb.append(" day(s) at ");
				sb.append(ruleParams.get(JobRuleTypeConstants.ONDAYS_TIME_INDEX).getValue());

				return sb.toString();
			} else if (selectedRuletypeName.equals(JobRuleTypeConstants.ONDATE_RULE)) {
				List<RuleParameter> ruleParams = rule.getParams();

				StringBuilder sb = new StringBuilder();
				sb.append("On ");
				sb.append(ruleParams.get(JobRuleTypeConstants.DATE_INDEX).getValue());
				sb.append(" at ");
				sb.append(ruleParams.get(JobRuleTypeConstants.ONDATE_TIME_INDEX).getValue());

				return sb.toString();
			} else if (selectedRuletypeName.equals(JobRuleTypeConstants.ON_DAY_EVERY_N_WEEKS_RULE)) {
				List<RuleParameter> ruleParams = rule.getParams();

				StringBuilder sb = new StringBuilder();
				sb.append("On ");
				sb.append(ruleParams.get(JobRuleTypeConstants.DAY_INDEX).getValue());
				sb.append(" every ");
				sb.append(ruleParams.get(JobRuleTypeConstants.WEEK_INDEX).getValue());
				sb.append(" week(s) at ");
				sb.append(ruleParams.get(JobRuleTypeConstants.ONDAY_TIME_INDEX).getValue());

				return sb.toString();
			}
		} catch (RuntimeException e) {
			logger.error("Error while preparing rule param string: " + e.toString());
		}
		return "";
	}

}
