/*
 * 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.metadata;

import com.jaspersoft.jasperserver.api.common.domain.ValidationResult;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jaspersoft.jasperserver.api.metadata.common.domain.FileResource;
import com.jaspersoft.jasperserver.api.metadata.common.service.RepositoryService;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JdbcReportDataSource;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportDataSource;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.MondrianConnection;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.MondrianXMLADefinition;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.OlapClientConnection;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.OlapUnit;
import com.jaspersoft.jasperserver.api.metadata.olap.service.OlapConnectionService;
import com.jaspersoft.jasperserver.api.metadata.olap.service.impl.OlapConnectionServiceImpl;
import com.jaspersoft.jasperserver.util.test.BaseJasperServerTest;

import junit.framework.TestCase;

/**
 * @author jshih
 */

//
// todo: TK: The resources created in this unit-test have the old uri path of /olap.
//           The Standard Sample Data uses /analysis. So, are the resources created in
//           this unit-test used (or are these deleted somewhere else)?
//

public class OlapClientTest extends BaseJasperServerTest {

	protected final Log log = LogFactory.getLog(this.getClass());

	protected final String OLAP_SCHEMAS = "/analysis/schemas/";

	protected final String OLAP_DATASOURCES = "/analysis/datasources/";

	protected final String OLAP_CONNECTIONS = "/analysis/connections/";

	protected final String OLAP_DEFINITIONS = "/analysis/xmla/definitions/";

	protected final String OLAP_VIEWS = "/analysis/views/";

    protected final String MDX_QUERY =
    	"SELECT {[Measures].[Unit Sales]} ON COLUMNS, " +
    	"{[Time].[1997].[Q1]} ON ROWS FROM [Sales]";

    protected final String XML_SCHEMA = "/analysis/schemas/Foodmart";

    private final static String strSchemaFoodmart = "FoodmartSchema";

    private final static String strSchemaSugarCrm = "SugarCRMSchema";

    private final static String strDatasourceFoodmart = "FoodmartDataSourceJNDI";

    private final static String strDatasourceSugarCrm = "SugarCRMDataSource";

	static String strConnection  = "Foodmart";

	private OlapClientConnection connectionOriginal;

    private OlapConnectionService connectionService;

	protected void onTearDown() {

        if (connectionOriginal != null) {
            connectionOriginal =
                (OlapClientConnection) getRepositoryService().getResource(null, OLAP_CONNECTIONS + strConnection);

            // change schema back to Foodmart
            ((MondrianConnection) connectionOriginal).setSchemaReference(OLAP_SCHEMAS + strSchemaFoodmart);

            // change datasource back to Foodmart
            ((MondrianConnection) connectionOriginal).setDataSourceReference(OLAP_DATASOURCES + strDatasourceFoodmart);

            getRepositoryService().saveResource(null, connectionOriginal);
        }
	}

    // tests

    static FileResource schemaFoodmart;

    static FileResource schemaSugarCrm;

    public void testSchemasExist()
	{
    	schemaFoodmart =
    		(FileResource) getRepositoryService().getResource(null, OLAP_SCHEMAS + strSchemaFoodmart);

        assertNotNull("Foodmart schema does not exist", schemaFoodmart);

    	assertNotNull("no data in Foodmart schema", schemaFoodmart.getDataStream());

    	schemaSugarCrm =
    		(FileResource) getRepositoryService().getResource(null, OLAP_SCHEMAS + strSchemaSugarCrm);

        assertNotNull("SugarCRM schema does not exist", schemaSugarCrm);

    	assertNotNull("no data in SugarCRM schema", schemaSugarCrm.getDataStream());

	}

	static ReportDataSource datasourceFoodmart;

   	static ReportDataSource datasourceSugarCrm;

    public void testDatasourcesExist()
    {
    	datasourceFoodmart =
    		(ReportDataSource) getRepositoryService().getResource(null, OLAP_DATASOURCES + strDatasourceFoodmart);

        assertNotNull("Foodmart data source does not exist", datasourceFoodmart);

    	datasourceSugarCrm =
    		(ReportDataSource) getRepositoryService().getResource(null, OLAP_DATASOURCES + strDatasourceSugarCrm);

        assertNotNull("SugarCRM data source does not exist", datasourceSugarCrm);

//    	String strDsFoodmart = "FoodmartDS";
//        JdbcReportDataSource datasource =
//        	(JdbcReportDataSource) getRepositoryService().newResource( null, JdbcReportDataSource.class );
//        datasource.setName(strDsFoodmart);
//        datasource.setLabel(strDsFoodmart);
//        datasource.setDescription(strDsFoodmart);
//        datasource.setDriverClass(jdbcProps.getProperty("foodmart.jdbc.driverClassName"));
//        datasource.setConnectionUrl(jdbcProps.getProperty("foodmart.jdbc.url"));
//        datasource.setUsername(jdbcProps.getProperty("foodmart.jdbc.username"));
//        datasource.setPassword(jdbcProps.getProperty("foodmart.jdbc.password"));
////        getConnectionService().saveResource( null, "/olap/datasources/", datasource );
//        getRepositoryService().saveResource(null, datasource);
//
//    	datasourceFoodmart =
//    		(ReportDataSource) getRepositoryService().getResource(null, OLAP_DATASOURCES + strDsFoodmart);
//
//    	assertTrue(datasourceFoodmart.getURIString().equals("/olap/datasources/FoodmartDS"));
    }

    private void setupTestMondrianConnection() {

    	connectionOriginal =
    		(OlapClientConnection) getRepositoryService().getResource(null, OLAP_CONNECTIONS + strConnection);

    	assertNotNull(connectionOriginal);

    	assertTrue(connectionOriginal instanceof MondrianConnection);

    	assertTrue(((MondrianConnection) connectionOriginal).getSchema().getReferenceLookup().getName()
    			.equals("FoodmartSchema"));

    	assertTrue(((MondrianConnection) connectionOriginal).getSchema().getReferenceURI()
    			.equals(OLAP_SCHEMAS + "FoodmartSchema"));
    }

	public void testUpdateMondrianConnectionSchema() {

		setupTestMondrianConnection();

    	// change schema to SugarCRM
    	((MondrianConnection) connectionOriginal).setSchemaReference(OLAP_SCHEMAS + strSchemaSugarCrm);

    	getRepositoryService().saveResource(null, connectionOriginal);

    	OlapClientConnection connectionNew =
    		(OlapClientConnection) getRepositoryService().getResource(null, OLAP_CONNECTIONS + strConnection);

    	assertNotNull(connectionNew);

    	assertTrue(connectionNew instanceof MondrianConnection);

    	assertTrue(((MondrianConnection) connectionNew).getSchema().getReferenceLookup().getName()
    			.equals("SugarCRMSchema"));

    	assertTrue(((MondrianConnection) connectionNew).getSchema().getReferenceURI()
    			.equals(OLAP_SCHEMAS + "SugarCRMSchema"));

    }

    public void testUpdateMondrianConnectionDatasource() {

    	setupTestMondrianConnection();

    	// new datasource
    	((MondrianConnection) connectionOriginal).setDataSourceReference(OLAP_DATASOURCES + strDatasourceSugarCrm);

    	getRepositoryService().saveResource(null, connectionOriginal);

    	OlapClientConnection connectionNew =
    		(OlapClientConnection) getRepositoryService().getResource(null, OLAP_CONNECTIONS + strConnection);

    	assertNotNull(connectionNew);

    	assertTrue(connectionNew instanceof MondrianConnection);

    	assertTrue(((MondrianConnection) connectionNew).getDataSource().getReferenceLookup().getName()
    			.equals("SugarCRMDataSource"));

    	assertTrue(((MondrianConnection) connectionNew).getDataSource().getReferenceURI()
    			.equals(OLAP_DATASOURCES + "SugarCRMDataSource"));

    }

    public void testXmlaDefinitionExists()
    {
    	String strDefinition = "FoodmartXmlaDefinition";

    	MondrianXMLADefinition definition =
    		(MondrianXMLADefinition) getRepositoryService().getResource(null, OLAP_DEFINITIONS + strDefinition);

    	assertNotNull(definition.getURIString()); // null
    }

    public void testXmlaConnectionExists()
    {
    	String strXMLAConnection = "FoodmartXmlaConnection";

    	OlapClientConnection connection =
    		(OlapClientConnection) getRepositoryService().getResource(null, OLAP_CONNECTIONS + strXMLAConnection);

    	assertNotNull(connection);
    }

    public void testOlapConnectionlParsesQuery()
    {
    	String olapViewRef = OLAP_CONNECTIONS + "Foodmart";

    	String olapQuery = MDX_QUERY;

        mondrian.olap.Connection mondrianConnection =
        	((OlapConnectionServiceImpl) getConnectionService()).getMondrianConnection(null, olapViewRef);

        mondrian.olap.Query mondrianQuery = mondrianConnection.parseQuery(olapQuery);

        assertNotNull(mondrianQuery);

        assertTrue(mondrianQuery.getCube().toString().equals("Sales"));
    }

    public void testOlapViewQuery()
    {
    	String strOlapView = "Foodmart_sample";

    	OlapUnit olapView =
    		(OlapUnit) getRepositoryService().getResource(null, OLAP_VIEWS + strOlapView);

    	assertNotNull(olapView.getOlapClientConnection());

    	assertTrue(olapView.getMdxQuery()
    			.equals(OlapConnectionTest.SAMPLE_FOODMART_MDX_QUERY));
    }

    // helpers
    public OlapConnectionService getConnectionService()
    {
        return connectionService;
    }

    public void setConnectionService(OlapConnectionService connection)
    {
        this.connectionService = connection;
    }
}
