/*
 * 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.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import javax.naming.NamingException;

import junit.textui.TestRunner;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;

import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.common.domain.ValidationDetail;
import com.jaspersoft.jasperserver.api.common.domain.ValidationResult;
import com.jaspersoft.jasperserver.api.common.domain.impl.ExecutionContextImpl;
import com.jaspersoft.jasperserver.api.engine.common.domain.Result;
import com.jaspersoft.jasperserver.api.engine.jasperreports.domain.impl.ReportUnitRequest;
import com.jaspersoft.jasperserver.api.engine.jasperreports.domain.impl.ReportUnitResult;
import com.jaspersoft.jasperserver.api.engine.jasperreports.domain.impl.TrialReportUnitRequest;
import com.jaspersoft.jasperserver.api.metadata.common.domain.FileResource;
import com.jaspersoft.jasperserver.api.metadata.common.domain.Resource;
import com.jaspersoft.jasperserver.api.metadata.common.domain.ResourceReference;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportUnit;
import com.jaspersoft.jasperserver.util.test.BaseJasperServerTest;


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

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

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

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

	/**
	 *
	 */
	public void testExecute() throws Exception	{
		// make a reportunit, execute it, and delete it
		FileResource reportRes = (FileResource) getRepositoryService().newResource(null, FileResource.class);
		reportRes.setFileType(FileResource.TYPE_JRXML);
		setCommon(reportRes, "EmployeesJRXML");
		InputStream jrxml = getClass().getResourceAsStream("/reports/jasper/Employees.jrxml");
		reportRes.readData(jrxml);
		ReportUnit unit = (ReportUnit) getRepositoryService().newResource(null, ReportUnit.class);
		unit.setName("Employees_JDBC");
		unit.setLabel("Employees_JDBC");
		unit.setParentFolder("/reports/samples");
		unit.setDataSourceReference("/datasources/JServerJdbcDS");
		unit.setMainReport(reportRes);

		getRepositoryService().saveResource(null, unit);

		ReportUnitResult result = (ReportUnitResult) getEngineService().execute(context, new ReportUnitRequest("/reports/samples/Employees_JDBC", new HashMap()));
		assertNotNull(result);
		JasperPrint jasperPrint = result.getJasperPrint();
		assertNotNull(jasperPrint);
		List pages = jasperPrint.getPages();
		assertNotNull(pages);
		assertTrue(pages.size() > 0);

		getRepositoryService().deleteResource(null,"/reports/samples/Employees_JDBC");
	}

	/**
	 *
	 */
	public void testGetResources() throws Exception	{
		ReportUnit reportUnit = (ReportUnit) getRepositoryService().getResource(context, "/reports/samples/AllAccounts");
		assertNotNull(reportUnit);
		ResourceReference reportRef = reportUnit.getMainReport();
		assertNotNull(reportRef);
		assertTrue(reportRef.isLocal());
		Resource report = reportRef.getLocalResource();
		assertNotNull(report);
		assertTrue(report instanceof FileResource);
		Resource[] resources = getEngineService().getResources(new ResourceReference(report));
		assertNotNull(resources);
		assertTrue(resources.length == 2);
	}

	public void testValidate() {
		ReportUnit unit = createUnit();

		ValidationResult result = getEngineService().validate(null, unit);
		assertNotNull(result);
		assertEquals(ValidationResult.STATE_ERROR, result.getValidationState());
		List results = result.getResults();
		assertNotNull(results);
		assertTrue(results.size() >= 1);
		ValidationDetail detail = (ValidationDetail) results.get(0);
		assertNotNull(detail);
		assertEquals("SalesByMonthTrialReport", detail.getName());

		addJar(unit);

		result = getEngineService().validate(null, unit);
		assertNotNull(result);
		assertEquals(ValidationResult.STATE_VALID, result.getValidationState());
	}

	public void testTrialExecute() {
		ReportUnit unit = createUnit();
		addJar(unit);

		TrialReportUnitRequest request = new TrialReportUnitRequest(unit, null);
		Result result = getEngineService().execute(null, request);
		assertNotNull(result);
		assertTrue(result instanceof ReportUnitResult);
		ReportUnitResult ruRes = (ReportUnitResult) result;
		JasperPrint print = ruRes.getJasperPrint();
		assertNotNull(print);
		List pages = print.getPages();
		assertNotNull(pages);
		assertTrue(pages.size() > 1);
	}

	private ReportUnit createUnit() {
		ReportUnit unit = (ReportUnit) getRepositoryService().newResource(null,
				ReportUnit.class);
		setCommon(unit, "SalesByMonthTrial");
		unit.setParentFolder("/reports");

		FileResource mainReport = (FileResource) getRepositoryService().newResource(null, FileResource.class);
		mainReport.setFileType(FileResource.TYPE_JRXML);
		setCommon(mainReport, "SalesByMonthTrialReport");
		mainReport.readData(getClass().getResourceAsStream("/reports/jasper/SalesByMonth.jrxml"));
		unit.setMainReport(mainReport);

		unit.setDataSourceReference("/datasources/JServerJdbcDS");

		FileResource img = (FileResource) getRepositoryService().newResource(null, FileResource.class);
		img.setFileType(FileResource.TYPE_IMAGE);
		img.readData(getClass().getResourceAsStream("/images/jasperreports.png"));
		setCommon(img, "Logo");
		unit.addResource(img);

		FileResource subrep = (FileResource) getRepositoryService().newResource(null, FileResource.class);
		subrep.setFileType(FileResource.TYPE_JRXML);
		subrep.readData(getClass().getResourceAsStream("/reports/jasper/SalesByMonthDetail.jrxml"));
		setCommon(subrep, "SalesByMonthDetail");
		unit.addResource(subrep);

		FileResource resBdl = (FileResource) getRepositoryService().newResource(null, FileResource.class);
		resBdl.setFileType(FileResource.TYPE_RESOURCE_BUNDLE);
		resBdl.readData(getClass().getResourceAsStream("/resource_bundles/sales.properties"));
		setCommon(resBdl, "sales.properties");
		unit.addResource(resBdl);

		return unit;
	}


	private void addJar(ReportUnit unit) {
		FileResource jar = (FileResource) getRepositoryService().newResource(null,
				FileResource.class);
		jar.setFileType(FileResource.TYPE_JAR);
		jar.readData(getClass().getResourceAsStream("/jars/scriptlet.jar"));
		setCommon(jar, "Scriptlet");
		unit.addResource(jar);
	}


	private void setCommon(Resource res, String id) {
		res.setName(id);
		res.setLabel(id + "_label");
		res.setDescription(id + " description");
	}

	public void testGetMainJasperReport() {
		JasperReport jasperReport = getEngineService().getMainJasperReport(null, "/reports/samples/AllAccounts");
		assertNotNull(jasperReport);
		assertEquals("AllAccounts", jasperReport.getName());
	}

	public void testExecuteWithCustomDS() throws Exception	{
		ReportUnitResult result = (ReportUnitResult) getEngineService().execute(context, new ReportUnitRequest("/reports/samples/DataSourceReport", new HashMap()));
		assertNotNull(result);
		JasperPrint jasperPrint = result.getJasperPrint();
		assertNotNull(jasperPrint);
		List pages = jasperPrint.getPages();
		assertNotNull(pages);
		assertTrue(pages.size() > 0);
	}

	public void testExecuteWithTableModelDS() throws Exception	{
		ReportUnitResult result = (ReportUnitResult) getEngineService().execute(context, new ReportUnitRequest("/reports/samples/DataSourceTableModel", new HashMap()));
		assertNotNull(result);
		JasperPrint jasperPrint = result.getJasperPrint();
		assertNotNull(jasperPrint);
		List pages = jasperPrint.getPages();
		assertNotNull(pages);
		assertTrue(pages.size() > 0);
	}

	public void testRemoveCustomDataSourceResources() {
		deleteResource("/reports/samples/DataSourceReport");
		deleteResource("/reports/samples/DataSourceTableModel");
		deleteResource("/reports/samples/DataSourceReportTemplate");
		deleteResource("/datasources/CustomDSFromBean");
		deleteResource("/datasources/CustomTableModelDS");
	}

	public void deleteResource(String uri) {
		Resource result = getRepositoryService().getResource(null, uri);
		assertNotNull(result);
		getRepositoryService().deleteResource(null, uri);
	}

}
