package gov.va.med.esr.service.impl;

// Java classes
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.math.RandomUtils;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.Trigger;

import gov.va.med.esr.common.clock.Clock;
import gov.va.med.esr.common.clock.Clock.Group;
import gov.va.med.esr.common.clock.Clock.Type;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.service.ScheduledTaskService;
import gov.va.med.esr.service.trigger.ClockTriggerEvent;
import gov.va.med.fw.cache.TriggerEventCacheManager;
import gov.va.med.fw.scheduling.SchedulingService;
import gov.va.med.fw.service.AbstractComponent;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.StopWatchLogger;

/**
 * Provides services related to scheduled tasks.
 * 
 * @author Carlos Ruiz
 * @version 1.0
 */
public class ScheduledTaskServiceImpl extends AbstractComponent implements ScheduledTaskService {
    private static final long serialVersionUID = -7330225195956530898L;
    
    private static final int ONE_DAY_HOURS = 24;
    private static final int ONE_HOUR_MINS = 60;
  
    private SchedulingService schedulingService = null;
    private TriggerEventCacheManager triggerEventCacheManager;  
    private boolean asyncClockMode;
    
    private String scheduledJobVOAClockProcessName = null;
    private String scheduledJobPHClockProcessName = null;
    private String scheduledJobSSNClockProcessName = null;
    private String scheduledJobWfClockProcessName = null;    
    private String scheduledJobZ11ClockProcessName = null;    
   
    /** These three properties can be very useful in tapping into unused cpu during low-peak
     * levels throughout the day.  For example, if the cpi is taxed heavily between 12am and 5am,
     * this allows for clocks to not also fire in that time frame.
     * 
     * However, there is a chance (if allowClocksToScatterAcrossDayBoundary=false) that these
     * could be counter-productive if the heavy cpu time is at the end of the 24 day.  In cases where it is not
     * viable (per requirements) to set allowClocksToScatterAcrossDayBoundary=true, the
     * disallowClocksToScatterIfProcessingAfterHour property will control, after which time, to not scatter.
     */
    private int scatterClockFactor;    
    private boolean allowClocksToScatterAcrossDayBoundary = false; // default
    private int disallowClocksToScatterIfProcessingAfterHour = 20; // default
    
    private double ph14DayLetterDays = 14;
    private double ph37DayLetterDays = 37;
    private double ssnVerificationLetterDays = 30;
    private double pseudoSsnLetterDays = 30;
    private double pseudoSsnReminderLetterDays = 30;
    
    private double voa3DayPendingDays = 3;
    private double msQueryPendingHours = 72;    
    private double z11PendingTraitsMins = 10;    
    
    /**
     * @see gov.va.med.fw.service.AbstractComponent#afterPropertiesSet()
     */
    public void afterPropertiesSet() throws Exception {
        super.afterPropertiesSet();
        
        Validate.notNull(schedulingService, "schedulingService is required");
        Validate.notNull(triggerEventCacheManager, "triggerEventCacheManager is required");
        
        Validate.notNull(scheduledJobPHClockProcessName, "scheduledJobPHClockProcessName is required.");
        Validate.notNull(scheduledJobSSNClockProcessName, "scheduledJobSSNClockProcessName is required.");
        
        Validate.isTrue(voa3DayPendingDays > 0, "voa3DayPendingDays must be greater than zero.", voa3DayPendingDays);
        Validate.isTrue(ph14DayLetterDays > 0, "ph14DayLetterDays must be greater than zero.", ph14DayLetterDays);
        Validate.isTrue(ph37DayLetterDays > 0, "ph37DayLetterDays must be greater than zero.", ph37DayLetterDays);
        Validate.isTrue(ssnVerificationLetterDays > 0, "ssnVerificationLetterDays must be greater than zero.", ssnVerificationLetterDays);
        Validate.isTrue(pseudoSsnLetterDays > 0, "pseudoSsnLetterDays must be greater than zero.", pseudoSsnLetterDays);
        Validate.isTrue(pseudoSsnReminderLetterDays > 0, "pseudoSsnReminderLetterDays must be greater than zero.", pseudoSsnReminderLetterDays);
        Validate.isTrue(z11PendingTraitsMins > 0, "z11PendingTraitsMins must be greater than zero.", z11PendingTraitsMins);
        
        voa3DayPendingDays = voa3DayPendingDays * ONE_DAY_HOURS;
        
        ph14DayLetterDays = ph14DayLetterDays * ONE_DAY_HOURS;
        ph37DayLetterDays = ph37DayLetterDays * ONE_DAY_HOURS;
        ssnVerificationLetterDays = ssnVerificationLetterDays * ONE_DAY_HOURS;
        pseudoSsnLetterDays = pseudoSsnLetterDays * ONE_DAY_HOURS;
        pseudoSsnReminderLetterDays = pseudoSsnReminderLetterDays * ONE_DAY_HOURS;
        
        z11PendingTraitsMins = z11PendingTraitsMins / ONE_HOUR_MINS;
    }
    
    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#cancelClock(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.clock.Clock.Type, gov.va.med.esr.common.clock.Clock.Group)
     */
    public void cancelClock(Person person, Type type, Group group) throws ServiceException {
        this.cancelClock(person, type, group, null);
    }
    
    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#cancelClock(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.clock.Clock.Type, gov.va.med.esr.common.clock.Clock.Group, java.lang.String)
     */
    public void cancelClock(Person person, Type type, Group group, String subject) throws ServiceException {
        Validate.notNull(person, "The person must not be null");
        Validate.notNull(person.getEntityKey(), "The person must already exist in database");        
        Validate.notNull(type, "The clock type must not be null");         
        Validate.notNull(group, "The group name must not be null");               
        String triggerName = person.getPersonEntityKey().getKeyValueAsString() + type.getName();        

        if (subject != null) {
            triggerName = triggerName + subject; 
        }
        
        doCancelClock(person.getPersonEntityKey(), triggerName, group.getName());
    }
    
    public void cancelClock(ClockTriggerEvent event) throws ServiceException {
    	try {
    		this.getSchedulingService().unschedule(event.getTriggerName(), event.getTriggerGroup()); // note this should internally check to see if necessary to unschedule
		} catch(Exception e) {
			throw new ServiceException("Unable to cancel clock from ClockTriggerEvent for trigger: " + event.getTriggerName(), e);
		}    	
    }
    
    private void doCancelClock(PersonEntityKey personId, String triggerName, String triggerGroup) throws ServiceException {
        try {
        	if(!asyncClockMode) {
        		this.getSchedulingService().unschedule(triggerName, triggerGroup); // note this should internally check to see if necessary to unschedule
        	} else {
        		if(this.getSchedulingService().getTrigger(triggerName, triggerGroup) != null) {
        			ClockTriggerEvent event = new ClockTriggerEvent(ClockTriggerEvent.CANCEL_CLOCK, personId);
        			event.setTriggerName(triggerName);
        			event.setTriggerGroup(triggerGroup);
        			Set events = new HashSet();
        			events.add(event);
        			triggerEventCacheManager.storeTriggerEvents(events);
        		}
        	}
        }  catch (SchedulerException e) {
            throw new ServiceException("Unable to cancel a job", e);
        }              
    }
    

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startClock(gov.va.med.esr.common.model.person.Person, double, gov.va.med.esr.common.clock.Clock.Type, gov.va.med.esr.common.clock.Clock.Group, org.quartz.JobDetail)
     */
    public void startClock(Person person, double hours, Type type, Group group, String jobDetailBeanName) throws ServiceException {
        startClock(person, hours, type, group, jobDetailBeanName, null);
    }
    
    public void startClock(Person person, double hours, Type type, Group group, String jobDetailBeanName, String subject) throws ServiceException {
        Validate.notNull(person, "The person must not be null");
        Validate.notNull(person.getEntityKey(), "The person must already exist in database");        
        Validate.notNull(type, "The clock type must not be null");         
        Validate.notNull(group, "The group name must not be null");
        
        startClock(person.getPersonEntityKey(), hours, type, group, jobDetailBeanName, subject);
    }
    
    public void startClock( PersonEntityKey personId, double hours, Clock.Type type, Clock.Group group, String jobDetailBeanName, String subject ) throws ServiceException {
    	StopWatchLogger watch = null;
    	
    	Validate.notNull(personId, "The person must already exist in database");
        Validate.notNull(type, "The clock type must not be null");         
        Validate.notNull(group, "The group name must not be null");       

        String triggerName = personId.getKeyValueAsString() + type.getName();
        
        if (subject != null) {
            triggerName = triggerName + subject; 
        }
        
        if( logger.isDebugEnabled()) {
            watch = new StopWatchLogger("ScheduledTaskService starting clock for: " + triggerName);
            if (watch != null) {
            	watch.start();
            }
        }

        doStartClock(personId, type, hours, triggerName, group, jobDetailBeanName, subject);            	
    
       	if(logger.isDebugEnabled() && watch != null)
     		 watch.stopAndLog();
    }
    
    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startPseudoSSNReasonClock(gov.va.med.esr.common.model.person.Person, java.lang.String)
     */
    public void startPseudoSSNReasonClock(Person person, String subject) throws ServiceException {
        startClock(person, getPseudoSsnLetterDays(), Clock.Type.SSN_30_DAY_PSEUDO_SSN_REASON_CLOCK, Clock.Group.SSN_CLOCK_GROUP,
        		this.scheduledJobSSNClockProcessName, subject);
    }

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#cancelPseudoSSNReasonClock(gov.va.med.esr.common.model.person.Person, java.lang.String)
     */
    public void cancelPseudoSSNReasonClock(Person person, String subject) throws ServiceException {
        cancelClock(person, Clock.Type.SSN_30_DAY_PSEUDO_SSN_REASON_CLOCK, Clock.Group.SSN_CLOCK_GROUP, subject);
    }

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startPseudoSSNVerificationClock(gov.va.med.esr.common.model.person.Person, java.lang.String)
     */
    public void startPseudoSSNVerificationClock(Person person, String subject) throws ServiceException {
        startClock(person, getSsnVerificationLetterDays(), Clock.Type.SSN_30_DAY_PSEUDO_SSN_VERIFICATION_CLOCK, Clock.Group.SSN_CLOCK_GROUP,
        		this.scheduledJobSSNClockProcessName, subject);
    }

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startSSNInvalidLetterClock(gov.va.med.esr.common.model.person.Person, java.lang.String)
     */
    public void startSSNInvalidLetterClock(Person person, String subject) throws ServiceException {
        startClock(person, getSsnVerificationLetterDays(), Clock.Type.SSN_30_DAY_VALIDATION_CLOCK, Clock.Group.SSN_CLOCK_GROUP,
        		this.scheduledJobSSNClockProcessName, subject);
    }

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startPHLetterClock(gov.va.med.esr.common.model.person.Person)
     */
    public void startPHLetterClock(Person person) throws ServiceException {
        startClock(person, getPh37DayLetterDays(), Clock.Type.PH_37_DAY_CLOCK, Clock.Group.PH_CLOCK_GROUP,
        		this.scheduledJobPHClockProcessName);
    }

    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startPHPendingClock(gov.va.med.esr.common.model.person.Person)
     */
    public void startPHPendingClock(Person person) throws ServiceException {
        startClock(person, getPh14DayLetterDays(), Clock.Type.PH_14_DAY_CLOCK, Clock.Group.PH_CLOCK_GROUP,
        		this.scheduledJobPHClockProcessName);
    }

    /**
     * Start the PH pending clock.
     * 
     * @param person
     * @throws ServiceException
     */
    public void startVOAPendingClock(Person person) throws ServiceException
    {
        startClock(person, getPh14DayLetterDays(), Clock.Type.VOA_3_DAY_CLOCK, Clock.Group.VOA_CLOCK_GROUP,
        		this.scheduledJobVOAClockProcessName);
    }


    /**
	 * @see gov.va.med.esr.service.ScheduledTaskService#startMilServiceQueryClock(gov.va.med.esr.common.model.person.Person)
	 */
	public void startMilServiceQueryClock(Person person) throws ServiceException {
	    startClock(person, this.getMsQueryPendingHours(), Clock.Type.WF_72_HOUR_CLOCK, Clock.Group.WF_CLOCK_GROUP,
        		this.getScheduledJobWfClockProcessName());
	}

	/**
     * @see gov.va.med.esr.service.ScheduledTaskService#startSSNReminderLetterClock(gov.va.med.esr.common.model.person.Person)
     */
    public void startSSNReminderLetterClock(Person person) throws ServiceException {
        startClock(person, getPseudoSsnReminderLetterDays(), Clock.Type.SSN_45_DAY_CLOCK, Clock.Group.SSN_CLOCK_GROUP,
        		this.scheduledJobSSNClockProcessName);
    }    
    
    /**
     * @see gov.va.med.esr.service.ScheduledTaskService#startZ11PendingTraitsClock(gov.va.med.esr.common.model.person.Person)
     */
    public void  startZ11PendingTraitsClock(Person person) throws ServiceException {
        startClock(person, getZ11PendingTraitsMins(), Clock.Type.Z11_10_MIN_CLOCK, Clock.Group.Z11_CLOCK_GROUP,
        		this.scheduledJobZ11ClockProcessName);
    }

    
    public void startClock(ClockTriggerEvent event) throws ServiceException {
    	StopWatchLogger watch = null;
    	
    	try {
	    	Trigger trigger = schedulingService.getTrigger(event.getTriggerName(), event.getTriggerGroup());
	    	if(trigger != null && !Clock.Group.WF_CLOCK_GROUP.getName().equals(trigger.getGroup()))
	    		return;
	    	
	    	// doesn't already exist, start it
	    	JobDetail jobDetail = (JobDetail) this.getComponent(event.getJobDetailBeanName());
            jobDetail.setName(event.getTriggerName());
            jobDetail.setGroup(event.getTriggerGroup());	    	
	    	
            if( logger.isDebugEnabled() ) {
	            watch = new StopWatchLogger("ScheduledTaskService starting clock for: " + event.getTriggerName());
	            if (watch != null) {
	            	watch.start();
	            }
            }
            
            if (trigger != null && Clock.Group.WF_CLOCK_GROUP.getName().equals(trigger.getGroup())) {
            	// MSDS has to reschedule rather than continue with existing clock. 
            	long millis = ( (long)Math.round(event.getAdjustedHoursDelay() * 60) ) * 60 * 1000;
            	trigger.setStartTime(new Date(System.currentTimeMillis() + millis));	
            	schedulingService.reschedule(trigger.getJobName(), trigger.getGroup(),trigger); 	
            }
            else {
            	schedulingService.schedule(jobDetail, event.getClockData(), event.getAdjustedHoursDelay(), event.getTriggerName(),
            			event.getTriggerGroup());
            }
	    	
	       	if(logger.isDebugEnabled() && watch != null)
	     		 watch.stopAndLog();

    	} catch(Exception e) {
    		throw new ServiceException("Unable to start clock from ClockTriggerEvent for trigger: " + event.getTriggerName(), e);
    	}
    }
    
    private void doStartClock( PersonEntityKey personId,
            Clock.Type type,
            double hours,
            String name,
            Clock.Group group,
            String jobDetailBeanName,
            String subject) throws ServiceException {
        
        // Check if already triggered this clock
        try {
            Trigger trigger = this.getSchedulingService().getTrigger( name,  group.getName() );
            
            if(trigger != null && !Clock.Group.WF_CLOCK_GROUP.getName().equals(trigger.getGroup())) {
            	return; 
            }
        }
        catch (SchedulerException e) {
            throw new ServiceException("Unable to check if scheduled", e);
        }             
                        
        List list = new ArrayList();
        list.add(personId.getKeyValueAsString());
        list.add(type.getName());
        if (subject != null) {
            list.add(subject);            
        }
        
        // adjust hours for variability (if at all)
        hours = calculateHours(hours);
        
        try {
        	if(!asyncClockMode) {
        		JobDetail jobDetail = (JobDetail) getComponent(jobDetailBeanName);
                jobDetail.setName(name);
                jobDetail.setGroup(group.getName());

        		this.getSchedulingService().schedule( jobDetail, list, hours, name, group.getName() );
        	} else {
        		// create TriggerEvent
        		ClockTriggerEvent event = new ClockTriggerEvent(ClockTriggerEvent.START_CLOCK, personId);
        		event.setHoursDelay(hours);
        		event.setTriggerName(name);
        		event.setTriggerGroup(group.getName());
        		event.setClockData(list);
        		event.setJobDetailBeanName(jobDetailBeanName);
        		Set events = new HashSet();
        		events.add(event);
        		triggerEventCacheManager.storeTriggerEvents(events);
        	}        	
        }
        catch (SchedulerException e) {
            throw new ServiceException("Unable to schedule job", e);
        }        
    }
    
	private double calculateHours(double hours) {
		int currentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		
		if(this.scatterClockFactor <= 0 || currentHour >= this.disallowClocksToScatterIfProcessingAfterHour)
			return hours;
		
    	double newHours = hours;
    	if(this.allowClocksToScatterAcrossDayBoundary) {
			double percentage = RandomUtils.nextDouble(); // should be between 0.0 and 1.0
			newHours = hours + (this.scatterClockFactor * percentage); // adjust hours
    	} else {
    		// must cap it
    		double percentage = RandomUtils.nextDouble(); // should be between 0.0 and 1.0
    		newHours = hours + ((Math.min(this.scatterClockFactor, 23.99 - currentHour)) * percentage); // adjust hours
    	}
    	return newHours;
	}

	
    /**
     * @return Returns the schedulingService.
     */
    public SchedulingService getSchedulingService() {
        return schedulingService;
    }

    /**
     * @param schedulingService The schedulingService to set.
     */
    public void setSchedulingService(SchedulingService schedulingService) {
        this.schedulingService = schedulingService;
    }
   
    
    /**
     * @return Returns the ph14DayLetterDays.
     */
    public double getPh14DayLetterDays() {
        return ph14DayLetterDays;
    }
    
    /**
     * @param ph14DayLetterDays The ph14DayLetterDays to set.
     */
    public void setPh14DayLetterDays(double ph14DayLetterDays) {
        this.ph14DayLetterDays = ph14DayLetterDays;
    }
    
    /**
     * @return Returns the ph37DayLetterDays.
     */
    public double getPh37DayLetterDays() {
        return ph37DayLetterDays;
    }
    
    /**
     * @param ph37DayLetterDays The ph37DayLetterDays to set.
     */
    public void setPh37DayLetterDays(double ph37DayLetterDays) {
        this.ph37DayLetterDays = ph37DayLetterDays;
    }
    
    /**
     * @return Returns the pseudoSsnLetterDays.
     */
    public double getPseudoSsnLetterDays() {
        return pseudoSsnLetterDays;
    }
    
    /**
     * @param pseudoSsnLetterDays The pseudoSsnLetterDays to set.
     */
    public void setPseudoSsnLetterDays(double pseudoSsnLetterDays) {
        this.pseudoSsnLetterDays = pseudoSsnLetterDays;
    }
    
    /**
     * @return Returns the pseudoSsnReminderLetterDays.
     */
    public double getPseudoSsnReminderLetterDays() {
        return pseudoSsnReminderLetterDays;
    }
    
    /**
     * @param pseudoSsnReminderLetterDays The pseudoSsnReminderLetterDays to set.
     */
    public void setPseudoSsnReminderLetterDays(double pseudoSsnReminderLetterDays) {
        this.pseudoSsnReminderLetterDays = pseudoSsnReminderLetterDays;
    }
    
    /**
     * @return Returns the ssnVerificationLetterDays.
     */
    public double getSsnVerificationLetterDays() {
        return ssnVerificationLetterDays;
    }
    
    /**
     * @param ssnVerificationLetterDays The ssnVerificationLetterDays to set.
     */
    public void setSsnVerificationLetterDays(double ssnVerificationLetterDays) {
        this.ssnVerificationLetterDays = ssnVerificationLetterDays;
    }

	/**
	 * @return Returns the triggerEventCacheManager.
	 */
	public TriggerEventCacheManager getTriggerEventCacheManager() {
		return triggerEventCacheManager;
	}

	/**
	 * @param triggerEventCacheManager The triggerEventCacheManager to set.
	 */
	public void setTriggerEventCacheManager(
			TriggerEventCacheManager triggerEventCacheManager) {
		this.triggerEventCacheManager = triggerEventCacheManager;
	}

	/**
	 * @return Returns the asyncClockMode.
	 */
	public boolean isAsyncClockMode() {
		return asyncClockMode;
	}

	/**
	 * @param asyncClockMode The asyncClockMode to set.
	 */
	public void setAsyncClockMode(boolean asyncClockMode) {
		this.asyncClockMode = asyncClockMode;
	}

	/**
	 * @return Returns the scheduledJobPHClockProcessName.
	 */
	public String getScheduledJobPHClockProcessName() {
		return scheduledJobPHClockProcessName;
	}

	/**
	 * @param scheduledJobPHClockProcessName The scheduledJobPHClockProcessName to set.
	 */
	public void setScheduledJobPHClockProcessName(
			String scheduledJobPHClockProcessName) {
		this.scheduledJobPHClockProcessName = scheduledJobPHClockProcessName;
	}

	/**
	 * @return Returns the scheduledJobSSNClockProcessName.
	 */
	public String getScheduledJobSSNClockProcessName() {
		return scheduledJobSSNClockProcessName;
	}

	/**
	 * @param scheduledJobSSNClockProcessName The scheduledJobSSNClockProcessName to set.
	 */
	public void setScheduledJobSSNClockProcessName(
			String scheduledJobSSNClockProcessName) {
		this.scheduledJobSSNClockProcessName = scheduledJobSSNClockProcessName;
	}


	/**
	 * @return Returns the scatterClockFactor.
	 */
	public int getScatterClockFactor() {
		return scatterClockFactor;
	}

	/**
	 * @param scatterClockFactor The scatterClockFactor to set.
	 */
	public void setScatterClockFactor(int scatterClockFactor) {
		this.scatterClockFactor = scatterClockFactor;
	}

	/**
	 * @return Returns the allowClocksToScatterAcrossDayBoundary.
	 */
	public boolean isAllowClocksToScatterAcrossDayBoundary() {
		return allowClocksToScatterAcrossDayBoundary;
	}

	/**
	 * @param allowClocksToScatterAcrossDayBoundary The allowClocksToScatterAcrossDayBoundary to set.
	 */
	public void setAllowClocksToScatterAcrossDayBoundary(
			boolean allowClocksToScatterAcrossDayBoundary) {
		this.allowClocksToScatterAcrossDayBoundary = allowClocksToScatterAcrossDayBoundary;
	}

	/**
	 * @return Returns the disallowClocksToScatterIfProcessingAfterHour.
	 */
	public int getDisallowClocksToScatterIfProcessingAfterHour() {
		return disallowClocksToScatterIfProcessingAfterHour;
	}

	/**
	 * @param disallowClocksToScatterIfProcessingAfterHour The disallowClocksToScatterIfProcessingAfterHour to set.
	 */
	public void setDisallowClocksToScatterIfProcessingAfterHour(
			int disallowClocksToScatterIfProcessingAfterHour) {
		this.disallowClocksToScatterIfProcessingAfterHour = disallowClocksToScatterIfProcessingAfterHour;
	}

	public double getVoa3DayPendingDays() {
		return voa3DayPendingDays;
	}

	public void setVoa3DayPendingDays(double voa3DayPendingDays) {
		this.voa3DayPendingDays = voa3DayPendingDays;
	}

	/**
	 * @return the scheduledJobWfClockProcessName
	 */
	public String getScheduledJobWfClockProcessName() {
		return scheduledJobWfClockProcessName;
	}

	/**
	 * @param scheduledJobWfClockProcessName the scheduledJobWfClockProcessName to set
	 */
	public void setScheduledJobWfClockProcessName(
			String scheduledJobWfClockProcessName) {
		this.scheduledJobWfClockProcessName = scheduledJobWfClockProcessName;
	}

	
	public String getScheduledJobZ11ClockProcessName() {
		return scheduledJobZ11ClockProcessName;
	}

	public void setScheduledJobZ11ClockProcessName(
			String scheduledJobZ11ClockProcessName) {
		this.scheduledJobZ11ClockProcessName = scheduledJobZ11ClockProcessName;
	}

	/**
	 * @return the msQueryPendingHours
	 */
	public double getMsQueryPendingHours() {
		return msQueryPendingHours;
	}

	/**
	 * @param msQueryPendingHours the msQueryPendingHours to set
	 */
	public void setMsQueryPendingHours(double msQueryPendingHours) {
		this.msQueryPendingHours = msQueryPendingHours;
	}

	public double getZ11PendingTraitsMins() {
		return z11PendingTraitsMins;
	}

	public void setZ11PendingTraitsMins(double pendingTraitsMins) {
		z11PendingTraitsMins = pendingTraitsMins;
	}

}
