package it.unibz.inf.ontop.owlapi;

import com.google.common.collect.ImmutableList;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.semanticweb.owlapi.model.OWLException;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;

import java.io.IOException;
import java.sql.SQLException;

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

public class DenormalizedShippingTest extends AbstractOWLAPITest {

    @BeforeClass
    public static void before() throws OWLOntologyCreationException, SQLException, IOException {
        initOBDA("/shipping/create-db.sql", "/shipping/shipping.obda");
    }

    @AfterClass
    public static void after() throws OWLException, SQLException {
        release();
    }

    @Test
    public void testShipmentCountries1() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  ?s a :Shipment ; :from ?fromCountry ; :to ?toCountry . \n" +
                "  ?fromCountry a :Country . \n" +
                "  ?toCountry a :Country . \n" +
                "} ORDER BY ?s";

        String loweredSQL = checkReturnedValuesAndReturnSql(sparqlQuery, "s", ImmutableList.of(
                "<http://example.com/shipment/1>",
                "<http://example.com/shipment/2>"))
                .toLowerCase();
        assertFalse(loweredSQL.contains("union"));
        assertFalse(loweredSQL.contains("distinct"));
    }

    @Test
    public void testValues() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  VALUES ?year { 2019 2019 }\n" +
                "}";

        checkReturnedValues(sparqlQuery, "year", ImmutableList.of("\"2019\"^^xsd:integer", "\"2019\"^^xsd:integer"));
    }

    @Test
    public void testShipmentCountries2() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  ?s a :Shipment ; :from ?fromCountry ; :to ?toCountry . \n" +
                "  ?fromCountry a :Country . \n" +
                "  ?toCountry a :Country . \n" +
                "  VALUES ?year { 2019 2020 }\n" +
                "} ORDER BY ?s";

        String loweredSQL = checkReturnedValuesAndReturnSql(sparqlQuery, "s", ImmutableList.of(
                "<http://example.com/shipment/1>", "<http://example.com/shipment/1>",
                "<http://example.com/shipment/2>", "<http://example.com/shipment/2>"))
                .toLowerCase();
        assertFalse(loweredSQL.contains("distinct"));
    }

    @Test
    public void testShipmentCountries3() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  ?s a :Shipment ; :from ?fromCountry ; :to ?toCountry . \n" +
                "  ?fromCountry a :Country ; :name ?fromCountryName . \n" +
                "  ?toCountry a :Country ; :name ?toCountryName . \n" +
                "} ORDER BY ?s";

        String loweredSQL = checkReturnedValuesAndReturnSql(sparqlQuery, "s", ImmutableList.of(
                "<http://example.com/shipment/1>",
                "<http://example.com/shipment/2>"))
                .toLowerCase();
        assertFalse(loweredSQL.contains("union"));
        assertFalse(loweredSQL.contains("distinct"));
    }

    @Test
    public void testShipmentCountries4() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  ?s a :Shipment ; :from ?fromCountry ; :to ?toCountry . \n" +
                "  ?fromCountry a :Country . \n" +
                "  ?toCountry a :EuropeanCountry . \n" +
                "} ORDER BY ?s";

        checkReturnedValuesAndReturnSql(sparqlQuery, "s", ImmutableList.of(
                "<http://example.com/shipment/1>"));
    }

    @Ignore("TODO: support lifting the common filter above the union")
    @Test
    public void testShipmentCountries5() throws Exception {
        String sparqlQuery = "PREFIX : <http://example.org/shipping/voc#>\n" +
                "SELECT * {\n" +
                "  ?s a :Shipment ; :from ?fromCountry ; :to ?toCountry . \n" +
                "  ?fromCountry a :Country . \n" +
                "  ?toCountry a :EuropeanCountry . \n" +
                "} ORDER BY ?s";

        String loweredSQL = checkReturnedValuesAndReturnSql(sparqlQuery, "s", ImmutableList.of(
                "<http://example.com/shipment/1>"));
        assertFalse(loweredSQL.contains("union"));
        assertFalse(loweredSQL.contains("distinct"));
    }
}
