/*
 *   Copyright 2011 Brian Rosenberger (Brutex Network)
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package net.brutex.xservices.ws.impl;

import static org.quartz.TriggerBuilder.newTrigger;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;

import javax.jws.WebService;

import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

import net.brutex.xservices.types.ScheduledJob;
import net.brutex.xservices.util.BrutexNamespaces;
import net.brutex.xservices.util.JobWrapper;
import net.brutex.xservices.ws.JobService;
import net.brutex.xservices.ws.XServicesFault;

/**
 * @author Brian Rosenberger
 * @since 0.5.0
 * 
 */
@WebService(targetNamespace = BrutexNamespaces.WS_XSERVICES, endpointInterface = "net.brutex.xservices.ws.JobService", serviceName = JobService.SERVICE_NAME)
public class JobServiceImpl implements JobService {

	
	public List<ScheduledJob> getJobList() throws XServicesFault {
		List<ScheduledJob> joblist = new ArrayList<ScheduledJob>();
		try {
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			List<String> jobgroups = scheduler.getJobGroupNames();
			for (String g : jobgroups) {
				GroupMatcher m = GroupMatcher.groupContains(g);
				Set<JobKey> keyset = scheduler.getJobKeys(m);
				for (JobKey key : keyset) {
					JobDataMap detail = scheduler.getJobDetail(key)
							.getJobDataMap();
					ScheduledJob job = new ScheduledJob(key.getName(),
							(GregorianCalendar) detail.get("date"),
							detail.getString("script"));
					joblist.add(job);
				}

			}

		} catch (SchedulerException e) {
			throw new XServicesFault(e);
		}
		return joblist;
	}

	
	public ScheduledJob getJob(String uuid) throws XServicesFault {
		try {
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			JobDetail job = scheduler.getJobDetail(new JobKey(uuid, "DEFAULT"));
			if (job == null)
				throw new XServicesFault("Job not found.");
			Trigger t = scheduler.getTrigger(new TriggerKey(uuid));
			GregorianCalendar cal = new GregorianCalendar(TimeZone.getDefault());
			cal.setTime(t.getStartTime());
			return new ScheduledJob(uuid, cal, job.getJobDataMap().getString(
					"script"), job.getDescription());
		} catch (SchedulerException e) {
			e.printStackTrace();
			throw new XServicesFault(e);
		}
	}

	
	public void deleteJob(String uuid) throws XServicesFault {
		try {
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			JobKey key = new JobKey(uuid, "DEFAULT");
			JobDetail job = scheduler.getJobDetail(key);
			if (job == null)
				throw new XServicesFault("Job not found.");
			Trigger t = scheduler.getTrigger(new TriggerKey(uuid));
			scheduler.deleteJob(key);
		} catch (SchedulerException e) {
			throw new XServicesFault(e);
		}

	}

	
	public String scheduleJob(ScheduledJob job) throws XServicesFault {
		try {
			// Grab the Scheduler instance from the Factory
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

			// and start it off

			if (!scheduler.isStarted())
				scheduler.start();
			if (scheduler.isInStandbyMode())
				scheduler.resumeAll();

			String identity = UUID.randomUUID().toString();
			//String identity = "test";
			JobDetail job2 = JobBuilder.newJob(JobWrapper.class)
					.withIdentity(identity).build();

			
			job2.getJobDataMap().put("script", job.getScript());
			job2.getJobDataMap().put("description", job.getDescription());
			job2.getJobDataMap().put("date", job.getDate());

			SimpleTrigger t = (SimpleTrigger) newTrigger()
					.withIdentity(identity).startAt(job.getDate().getTime())
					.build();
			;

			scheduler.scheduleJob(job2, t);
			return identity;
		} catch (SchedulerException e) {
			e.printStackTrace();
			throw new XServicesFault(e);
		}
	}

}
