package eu.dnetlib.dlms.impl.daos;

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

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
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.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import eu.dnetlib.dlms.impl.hibobjects.RepositoryWrapper;
import eu.dnetlib.dlms.lowlevel.LowLevelException;
import eu.dnetlib.dlms.lowlevel.objects.RelationSet;
import eu.dnetlib.dlms.lowlevel.objects.Set;
import eu.dnetlib.dlms.lowlevel.objects.structures.Structure;
import eu.dnetlib.dlms.lowlevel.types.AtomType;
import eu.dnetlib.dlms.lowlevel.types.AtomTypeDAO;
import eu.dnetlib.dlms.lowlevel.types.RelationSetType;
import eu.dnetlib.dlms.lowlevel.types.RelationSetTypeDAO;
import eu.dnetlib.dlms.lowlevel.types.RelationType;
import eu.dnetlib.dlms.lowlevel.types.RelationTypeDAO;
import eu.dnetlib.dlms.lowlevel.types.SetType;
import eu.dnetlib.dlms.lowlevel.types.SetTypeDAO;

/**
 * @author lexis
 * 
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ExtRelationSetDAOHibernateTest {

	/**
	 * logger.
	 */
	private static final Log log = LogFactory.getLog(ExtRelationSetDAOHibernateTest.class);
	/** DAO for RelationType. */
	@Resource
	private RelationTypeDAO relTypeDAO;
	/** DAO for RelationSetType. */
	@Resource
	private RelationSetTypeDAO relSetTypeDAO;
	/**
	 *DAO for RelationSet, instance under test.
	 */
	@Resource
	private ExtRelationSetDAOHibernate extRelSetDAO;

	/**
	 *DAO for Set.
	 */
	@Resource
	private ExtSetDAOHibernate extSetDAO;
	/**
	 * SetTypeDAO instance.
	 */
	@Resource
	private SetTypeDAO setTypeDAO;
	/** DAO for AtomType. */
	@Resource
	private AtomTypeDAO atomTypeDAO;

	/** Atom type. */
	@Resource
	private AtomType atomType1;
	/**
	 * SetTypes for Set of atoms.
	 */
	@Resource
	private SetType setType1, setType2;
	/**
	 * Sets of atoms.
	 */
	@Resource
	private Set atomSet1, atomSet2;
	/** RelationType instance. */
	@Resource
	private RelationType relType;
	/**
	 * RelationSetType.
	 */
	@Resource
	private RelationSetType relSetType;
	/**
	 * RelationSet.
	 */
	@Resource
	private RelationSet relSet;

	/** Triplestore. */
	@Resource
	private RepositoryWrapper repositoryWrapper;

	/**
	 * Init operations to execute before every test method.
	 * 
	 * @throws RepositoryException
	 *             accesing triplestore
	 */
	@Before
	public void before() throws RepositoryException {
		this.atomTypeDAO.save(this.atomType1);
		this.setTypeDAO.save(this.setType1);
		this.setTypeDAO.save(this.setType2);
		this.extSetDAO.save(this.atomSet1);
		this.extSetDAO.save(this.atomSet2);
		this.relTypeDAO.save(this.relType);
		this.relSetTypeDAO.save(this.relSetType);
		this.logTriples();
	}

	public void logTriples() {
		try {
			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();
		} catch (final Exception e) {
			throw new LowLevelException(e);
		}
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.impl.daos.ExtRelationSetDAOHibernate#save(eu.dnetlib.dlms.lowlevel.objects.RelationSet)}.
	 */
	@Test
	@DirtiesContext
	public void testSaveRelationSet() {
		this.extRelSetDAO.save(this.relSet);
		this.logTriples();
		//let's check if there is an entry for relSet in systemRelSets:
		final Structure struct = this.extRelSetDAO.getSystemSetHelper().findSystemStructureFor(this.relSet);
		assertNotNull(struct);
	}

	/**
	 * Test method for
	 * {@link eu.dnetlib.dlms.impl.daos.ExtRelationSetDAOHibernate#delete(eu.dnetlib.dlms.lowlevel.objects.RelationSet)}
	 * .
	 */
	@Test
	@DirtiesContext
	public void testDeleteRelationSet() {
		this.extRelSetDAO.save(this.relSet);
		//let's check if there is an entry for relSet in systemRelSets:
		Structure struct = this.extRelSetDAO.getSystemSetHelper().findSystemStructureFor(this.relSet);
		assertNotNull(struct);
		this.logTriples();
		this.extRelSetDAO.delete(this.relSet);
		this.logTriples();
		//let's check if there is an entry for relSet in systemRelSets:
		struct = this.extRelSetDAO.getSystemSetHelper().findSystemStructureFor(this.relSet);
		assertNull(struct);
	}

}
