/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.jaspersoft.jasperserver.ws.axis2.scheduling;

import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.axis.AxisFault;
import org.springframework.context.i18n.LocaleContextHolder;

import com.jaspersoft.jasperserver.api.JSException;
import com.jaspersoft.jasperserver.api.logging.audit.context.AuditContext;
import com.jaspersoft.jasperserver.api.logging.audit.domain.AuditEvent;
import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.common.domain.impl.ExecutionContextImpl;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJob;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobSummary;
import com.jaspersoft.jasperserver.api.engine.scheduling.service.ReportSchedulingService;
import com.jaspersoft.jasperserver.ws.scheduling.Job;
import com.jaspersoft.jasperserver.ws.scheduling.JobSummary;

/**
 * @author Lucian Chirita (lucianc@users.sourceforge.net)
 * @version $Id: ReportSchedulerServiceImpl.java 19933 2010-12-11 15:27:37Z tmatyashovsky $
 */
public class ReportSchedulerServiceImpl implements ReportSchedulerService {

	private ReportSchedulingService scheduler;
	private ReportJobBeanTraslator beanTraslator;
    private AuditContext auditContext;

    protected void createAuditReportSchedulingEvent(final String jobType) {
        auditContext.doInAuditContext(new AuditContext.AuditContextCallback() {
            public void execute() {
                auditContext.createAuditEvent(jobType);
            }
        });
    }

    protected void closeReportSchedulingAuditEvent(String jobType) {
        auditContext.doInAuditContext(jobType, new AuditContext.AuditContextCallbackWithEvent() {
            public void execute(AuditEvent auditEvent) {
                auditContext.closeAuditEvent(auditEvent);
            }
        });
    }

	public void deleteJob(long id) throws AxisFault {
        createAuditReportSchedulingEvent("deleteReportScheduling");
		scheduler.removeScheduledJob(makeExecutionContext(), id);
        closeReportSchedulingAuditEvent("deleteReportScheduling");
	}

	public void deleteJobs(long[] ids) throws AxisFault {
		scheduler.removeScheduledJobs(makeExecutionContext(), ids);
	}

	public Job getJob(long id) throws AxisFault {
		ReportJob reportJob = scheduler.getScheduledJob(makeExecutionContext(), id);
		if (reportJob == null) {
			throw new JSException("report.scheduling.ws.job.not.found", new Object[]{new Long(id)});
		}
		Job job = beanTraslator.toServiceBean(reportJob);
		return job;
	}

	public Job scheduleJob(Job job) throws AxisFault {
		ReportJob reportJob = new ReportJob();
		beanTraslator.copy(reportJob, job);
		reportJob.setVersion(ReportJob.VERSION_NEW);

        createAuditReportSchedulingEvent("scheduleReport");
		ReportJob savedJob = scheduler.scheduleJob(makeExecutionContext(), reportJob);
        closeReportSchedulingAuditEvent("scheduleReport");
		Job savedServiceJob = beanTraslator.toServiceBean(savedJob);
		return savedServiceJob;
	}

	public Job updateJob(Job job) throws AxisFault {
		ReportJob reportJob = new ReportJob();
		beanTraslator.copy(reportJob, job);
		ExecutionContext executionContext = makeExecutionContext();
        createAuditReportSchedulingEvent("updateReportScheduling");
		scheduler.updateScheduledJob(executionContext, reportJob);
        closeReportSchedulingAuditEvent("updateReportScheduling");
		ReportJob savedJob = scheduler.getScheduledJob(executionContext, reportJob.getId());
		Job savedServiceJob = beanTraslator.toServiceBean(savedJob);
		return savedServiceJob;
	}

	public JobSummary[] getAllJobs() throws AxisFault {
		List scheduledJobs = scheduler.getScheduledJobs(makeExecutionContext());
		return toSummaryArray(scheduledJobs);
	}

	public JobSummary[] getReportJobs(String reportURI) throws AxisFault {
		List scheduledJobs = scheduler.getScheduledJobs(makeExecutionContext(), reportURI);
		return toSummaryArray(scheduledJobs);
	}

	protected JobSummary[] toSummaryArray(List reportJobSummaries) {
		JobSummary[] jobs;
		if (reportJobSummaries == null || reportJobSummaries.isEmpty()) {
			jobs = null;
		} else {
			jobs = new JobSummary[reportJobSummaries.size()];
			int idx = 0;
			for (Iterator it = reportJobSummaries.iterator(); it.hasNext(); ++idx) {
				ReportJobSummary reportJob = (ReportJobSummary) it.next();
				jobs[idx] = beanTraslator.toServiceSummary(reportJob);
			}
		}
		return jobs;
	}

	protected ExecutionContext makeExecutionContext() {
		ExecutionContextImpl executionContext = new ExecutionContextImpl();
		executionContext.setLocale(getLocale());
		return executionContext;
	}
	
	protected Locale getLocale() {
		return LocaleContextHolder.getLocale();
	}
	
	public ReportSchedulingService getScheduler() {
		return scheduler;
	}

	public void setScheduler(ReportSchedulingService scheduler) {
		this.scheduler = scheduler;
	}

	public ReportJobBeanTraslator getBeanTraslator() {
		return beanTraslator;
	}

	public void setBeanTraslator(ReportJobBeanTraslator beanTraslator) {
		this.beanTraslator = beanTraslator;
	}

    public AuditContext getAuditContext() {
        return auditContext;
    }

    public void setAuditContext(AuditContext auditContext) {
        this.auditContext = auditContext;
    }
}
