/*
 * 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.api.engine.jasperreports.service.impl;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.naming.NamingException;

import junit.textui.TestRunner;

import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.common.domain.LogEvent;
import com.jaspersoft.jasperserver.api.common.domain.impl.ExecutionContextImpl;
import com.jaspersoft.jasperserver.api.engine.common.service.LoggingService;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJob;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobIdHolder;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobMailNotification;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobRepositoryDestination;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobSimpleTrigger;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobSource;
import com.jaspersoft.jasperserver.api.engine.scheduling.domain.ReportJobSummary;
import com.jaspersoft.jasperserver.api.engine.scheduling.quartz.ReportExecutionJob;
import com.jaspersoft.jasperserver.api.engine.scheduling.service.ReportJobsPersistenceService;
import com.jaspersoft.jasperserver.util.test.BaseJasperServerTest;


/**
 * @author Lucian Chirita (lucianc@users.sourceforge.net)
 * @version $Id: ReportSchedulingTest.java 19930 2010-12-11 15:17:19Z tmatyashovsky $
 */
public class ReportSchedulingTest extends BaseJasperServerTest
{
	private ReportJobsPersistenceService reportJobsPersistenceService;
	private ExecutionContext executionContext;
        private LoggingService loggingService;

        long eventId = -1;
        
	public LoggingService getLoggingService() {
			return loggingService;
		}


		public void setLoggingService(LoggingService loggingService) {
			this.loggingService = loggingService;
		}


	public ReportJobsPersistenceService getReportJobsPersistenceService() {
			return reportJobsPersistenceService;
		}


		public void setReportJobsPersistenceService(
				ReportJobsPersistenceService reportJobsPersistenceService) {
			this.reportJobsPersistenceService = reportJobsPersistenceService;
		}


	public ReportSchedulingTest(String name){
		super(name);
		setAutowireMode(AUTOWIRE_BY_NAME);
	}

	protected void onSetUp() throws Exception {
		executionContext = new ExecutionContextImpl();
	}

	protected void onTearDown() {
                if (eventId >= 0) {
                    loggingService.delete(null, new long[] { eventId });
                }
	}


	public static void main(String[] args) {
		TestRunner.run(ReportSchedulingTest.class);
	}

	public void testPersistence() {
		ReportJobSource source = new ReportJobSource();
		source.setReportUnitURI("/test/reportURI");
		Map params = new HashMap();
		params.put("param1", new Integer(5));
		params.put("param2", "value2");
		source.setParametersMap(params);

		Date startDate = new Date();
		ReportJobSimpleTrigger trigger = new ReportJobSimpleTrigger();
		trigger.setStartDate(startDate);
		trigger.setOccurrenceCount(20);
		trigger.setRecurrenceInterval(10);
		trigger.setRecurrenceIntervalUnit(ReportJobSimpleTrigger.INTERVAL_DAY);

		ReportJobRepositoryDestination repositoryDestination = new ReportJobRepositoryDestination();
		repositoryDestination.setFolderURI("/test/scheduled");
		repositoryDestination.setOutputDescription("report output");
		repositoryDestination.setSequentialFilenames(true);
		repositoryDestination.setTimestampPattern("yyyyMMdd");

		ReportJobMailNotification mailNotification = new ReportJobMailNotification();
		mailNotification.addTo("john@smith.com");
		mailNotification.setSubject("Scheduled report");
		mailNotification.setMessageText("Executed report");

		ReportJob job = new ReportJob();
		job.setLabel("foo");
		job.setDescription("bar");
		job.setSource(source);
		job.setTrigger(trigger);
		job.setBaseOutputFilename("foo");
		job.addOutputFormat(ReportJob.OUTPUT_FORMAT_PDF);
		job.addOutputFormat(ReportJob.OUTPUT_FORMAT_RTF);
		job.setContentRepositoryDestination(repositoryDestination);
		job.setMailNotification(mailNotification);

		job = reportJobsPersistenceService.saveJob(executionContext, job);
		assertNotNull(job);
		long jobId = job.getId();
		boolean deleted = true;
		try {
			job = reportJobsPersistenceService.loadJob(executionContext, new ReportJobIdHolder(jobId));
			assertNotNull(job);
			assertEquals("foo", job.getLabel());
			Set outputFormats = job.getOutputFormats();
			assertNotNull(outputFormats);
			assertEquals(2, outputFormats.size());
			assertTrue(outputFormats.contains(new Byte(ReportJob.OUTPUT_FORMAT_PDF)));
			assertTrue(outputFormats.contains(new Byte(ReportJob.OUTPUT_FORMAT_RTF)));

			source = job.getSource();
			assertNotNull(source);
			assertEquals("/test/reportURI", source.getReportUnitURI());
			params = source.getParametersMap();
			assertNotNull(params);
			assertEquals(2, params.size());
			assertTrue(params.containsKey("param1"));
			assertEquals(new Integer(5), params.get("param1"));
			assertTrue(params.containsKey("param2"));
			assertEquals("value2", params.get("param2"));

			assertNotNull(job.getTrigger());
			assertTrue(job.getTrigger() instanceof ReportJobSimpleTrigger);
			trigger = (ReportJobSimpleTrigger) job.getTrigger();
			assertEquals(20, trigger.getOccurrenceCount());
			assertNotNull(trigger.getRecurrenceIntervalUnit());
			assertEquals(ReportJobSimpleTrigger.INTERVAL_DAY, trigger.getRecurrenceIntervalUnit().byteValue());

			repositoryDestination = job.getContentRepositoryDestination();
			assertNotNull(repositoryDestination);
			assertEquals("/test/scheduled", repositoryDestination.getFolderURI());
			assertEquals("report output", repositoryDestination.getOutputDescription());
			assertTrue(repositoryDestination.isSequentialFilenames());
			assertEquals("yyyyMMdd", repositoryDestination.getTimestampPattern());
			assertFalse(repositoryDestination.isOverwriteFiles());

			mailNotification = job.getMailNotification();
			assertNotNull(mailNotification);
			assertEquals("Scheduled report", mailNotification.getSubject());
			List toAddresses = mailNotification.getToAddresses();
			assertNotNull(toAddresses);
			assertEquals(1, toAddresses.size());
			assertEquals("john@smith.com", toAddresses.get(0));

			long origJobId = job.getId();
			int origJobVersion = job.getVersion();
			long origTriggerId = trigger.getId();
			int origTriggerVersion = trigger.getVersion();
			long origMailId = mailNotification.getId();
			int origMailVersion = mailNotification.getVersion();
			job.setDescription("updated");
			mailNotification.setSubject("updated subject");
			mailNotification.addTo("joan@smith.com");
			mailNotification.addCc("mary@smith.com");
			reportJobsPersistenceService.updateJob(executionContext, job);
			job = reportJobsPersistenceService.loadJob(executionContext, new ReportJobIdHolder(jobId));
			assertNotNull(job);
			assertEquals("foo", job.getLabel());
			assertEquals("updated", job.getDescription());
			assertEquals(origJobId, job.getId());
			assertEquals(origJobVersion + 1, job.getVersion());
			assertNotNull(job.getTrigger());
			assertTrue(job.getTrigger() instanceof ReportJobSimpleTrigger);
			trigger = (ReportJobSimpleTrigger) job.getTrigger();
			assertEquals(origTriggerId, trigger.getId());
			assertEquals(origTriggerVersion, trigger.getVersion());
			mailNotification = job.getMailNotification();
			assertNotNull(mailNotification);
			assertEquals(origMailId, mailNotification.getId());
			assertEquals(origMailVersion + 1, mailNotification.getVersion());
			assertEquals("updated subject", mailNotification.getSubject());
			toAddresses = mailNotification.getToAddresses();
			assertEquals(2, toAddresses.size());
			assertEquals("john@smith.com", toAddresses.get(0));
			assertEquals("joan@smith.com", toAddresses.get(1));
			List ccAddresses = mailNotification.getCcAddresses();
			assertNotNull(ccAddresses);
			assertEquals(1, ccAddresses.size());
			assertEquals("mary@smith.com", ccAddresses.get(0));

			List jobs = reportJobsPersistenceService.listJobs(executionContext, "/test/reportURI");
			assertNotNull(jobs);
			assertTrue(1 <= jobs.size());
			boolean found = false;
			for (Iterator it = jobs.iterator(); it.hasNext();) {
				Object element = it.next();
				assertTrue(element instanceof ReportJobSummary);
				ReportJobSummary summary = (ReportJobSummary) element;
				if (summary.getId() == jobId) {
					found = true;
					assertEquals("foo", summary.getLabel());
					break;
				}
			}
			assertTrue(found);

			reportJobsPersistenceService.deleteJob(executionContext, new ReportJobIdHolder(jobId));
			deleted = true;
			job = reportJobsPersistenceService.loadJob(executionContext, new ReportJobIdHolder(jobId));
			assertNull(job);
		} finally {
			if (!deleted) {
				reportJobsPersistenceService.deleteJob(executionContext, new ReportJobIdHolder(jobId));
			}
		}
	}
        
        public void testLogging() {
		LogEvent event = loggingService.instantiateLogEvent();
		event.setComponent(ReportExecutionJob.LOGGING_COMPONENT);
		event.setType(LogEvent.TYPE_ERROR);
		event.setMessageCode("log.error.report.job.failed");
		
		StringWriter writer = new StringWriter();
		PrintWriter printWriter = new PrintWriter(writer);
		printWriter.println("Quartz Job: testJob");
		printWriter.println("Quartz Trigger: testTrigger");
		
		printWriter.println("Exceptions:");
                
                try {
                    int[] i = new int[2];
                    int j = i[5];
                    
                } catch (Exception e) {
                    e.printStackTrace(printWriter);
                }
		
		printWriter.flush();
		event.setText(writer.toString());
		event.setState(LogEvent.STATE_UNREAD);
		
		loggingService.log(event);
                
                eventId = event.getId();
            
        }
}
