package eu.dnetlib.dlms.epub.queries;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openrdf.model.Value;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.dlms.impl.hibobjects.RepositoryWrapper;
import eu.dnetlib.dlms.jdbc.DorotyDataSource;
import eu.dnetlib.dlms.jdbc.InformationObject;
import eu.dnetlib.dlms.lowlevel.objects.structures.DescriptionValueCollection;

/**
 * Test that executes queries on System Sets.
 * 
 * @author lexis
 * 
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class TestSystemSets {
	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(TestSystemSets.class);

	@Resource
	private DorotyDataSource dorotyDataSource;

	@Resource
	private RepositoryWrapper repositoryWrapper;

	/**
	 * Logs the triples currently in the store.
	 * 
	 * @throws RepositoryException
	 */
	public void logTriples() throws RepositoryException {
		final RepositoryConnection c = this.repositoryWrapper.getConnection();
		final RepositoryResult<org.openrdf.model.Statement> res = c.getStatements(null, null, (Value) null, false);
		int count = 0;
		while (res.hasNext()) {
			log.debug(res.next());
			count++;
		}
		log.debug("Total number of triples: " + count);
		res.close();
		this.repositoryWrapper.closeConnection();
	}

	/**
	 * Test for SystemSets: selects the name of all system sets.
	 * 
	 * @throws SQLException
	 *             , RepositoryException
	 */
	@Test
	public void testSystemSetNames() throws SQLException, RepositoryException {
		final Connection con = this.dorotyDataSource.getConnection();
		final Statement stm = con.createStatement();
		stm.execute("select SystemSets/@name");
		final ResultSet rs = stm.getResultSet();
		while (rs.next()) {
			log.debug(rs.getObject(1));
		}
		rs.close();
		stm.close();
		con.close();
		//this.logTriples();
	}

	/**
	 * Test for SystemStructSets: selects the identifier of all Structure Sets.
	 * 
	 * @throws SQLException
	 *             , RepositoryException
	 */
	@Test
	public void testSystemStructSetID() throws SQLException, RepositoryException {
		final Connection con = this.dorotyDataSource.getConnection();
		final Statement stm = con.createStatement();
		stm.execute("select SystemStructSets/@setID");
		final ResultSet rs = stm.getResultSet();
		while (rs.next()) {
			final Long id = (Long) rs.getObject(1);
			assertNotNull(id);
			log.debug("RS ROW: " + id);
		}
		rs.close();
		stm.close();
		con.close();
		//this.logTriples();
	}

	/**
	 * Test for SystemStructSets: selects the field called fields of type coll({label:string, type:string}) of Set
	 * ePrints.
	 * 
	 * @throws SQLException
	 *             , RepositoryException
	 */
	@Test
	public void testSystemStructSetColl() throws SQLException, RepositoryException {
		final Connection con = this.dorotyDataSource.getConnection();
		final Statement stm = con.createStatement();
		stm.execute("select SystemStructSets[@name='ePrints']/@fields");
		final ResultSet rs = stm.getResultSet();
		while (rs.next()) {
			log.debug("RS ROW:");
			final DescriptionValueCollection l = (DescriptionValueCollection) rs.getObject(1);
			log.debug(l);
		}
		rs.close();
		stm.close();
		con.close();
		//this.logTriples();
	}

	/**
	 *Test for SystemUnionSets: selects the entries that represent union sets.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void selectSystemUnionSet() throws SQLException {
		final PreparedStatement st = this.dorotyDataSource.getConnection().prepareStatement("select SystemUnionSets");
		st.execute();
		final ResultSet rs = st.getResultSet();
		log.debug("Reading result");
		assertTrue(rs.next());
		final InformationObject o = (InformationObject) rs.getObject(1);
		log.debug(o);
		assertNotNull(o);
		rs.close();
	}

	/**
	 * Test for SystemUnionSets: selects the name of Sets included by the UnionSet called Component.
	 * 
	 * @throws SQLException
	 */
	@Test
	public void selectComponents() throws SQLException {
		final PreparedStatement st = this.dorotyDataSource.getConnection().prepareStatement(
				"select SystemUnionSets[@name='Components']/SystemIncludesSets/@name");
		assertTrue(st.execute());
		final ResultSet rs = st.getResultSet();
		log.debug("Reading result");
		while (rs.next()) {
			final String s = rs.getString(1);
			log.debug(s);
			assertNotNull(s);
		}
		rs.close();
	}

}
