/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.sparql.junit ;

import java.util.ArrayList;
import java.util.List;

import org.apache.jena.query.Dataset;
import org.apache.jena.query.ResultSetFactory;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.sparql.resultset.ResultsFormat;
import org.apache.jena.sparql.resultset.SPARQLResult;
import org.apache.jena.sparql.vocabulary.TestManifest;
import org.apache.jena.sparql.vocabulary.TestManifestX;
import org.apache.jena.sparql.vocabulary.VocabTestQuery;
import org.apache.jena.util.FileManager;
import org.apache.jena.util.iterator.ClosableIterator;
import org.apache.jena.util.junit.TestException;
import org.apache.jena.util.junit.TestUtils;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;

/**
 * Wrapper class for individual test items. Assumes it is a query test item,
 * using both the manifest vocabulary and the test query vocabulary.
 */
public class TestItem
{
    static int counter = 0 ;

    public static String fakeURI() {
        return "test:" + (++counter) ;
    }

    private Resource     testResource     = null ;
    private Resource     actionResource   = null ;

    private String       name ;

    private boolean      buildLuceneIndex = false ;
    private String       resultFile ;
    private String       comment ;
    private List<String> defaultGraphURIs ;
    private List<String> namedGraphURIs ;
    private Resource     testType         = null ;
    private String       queryFile ;
    private Syntax       queryFileSyntax ;

    public static TestItem create(Resource entry, Resource defaultTestType) {
        return new TestItem(entry, defaultTestType) ;
    }

    public static TestItem create(String _name, String _queryFile, String _dataFile, String _resultFile) {
        return new TestItem(_name, _queryFile, _dataFile, _resultFile) ;
    }

    private TestItem(Resource entry, Resource defaultTestType) {
        testResource = entry ;

        if ( !entry.hasProperty(TestManifest.name) )
            throw new QueryTestException("TestItem with no name (" + entry + ")") ;
        name = _getName() ;

        if ( !entry.hasProperty(TestManifest.action) )
            throw new QueryTestException("TestItem '" + name + "' with no action") ;

        // Assumes one type per test only.
        testType = TestUtils.getResource(entry, RDF.type) ;
        if ( testType == null )
            testType = defaultTestType ;

        resultFile = _getResultFile() ;
        comment = _getComment() ;

        defaultGraphURIs = _getDefaultGraphURIs() ;
        namedGraphURIs = _getNamedGraphsURIs() ;

        queryFile = _getQueryFile() ;
        queryFileSyntax = _getQuerySyntax(entry.getModel(), queryFile, Syntax.syntaxARQ) ;
        buildLuceneIndex = _getTextIndex() ;
    }

    private TestItem(String _name, String _queryFile, String _dataFile, String _resultFile) {
        name = _name ;
        queryFile = _queryFile ;
        defaultGraphURIs = new ArrayList<>() ;
        defaultGraphURIs.add(_dataFile) ;
        namedGraphURIs = new ArrayList<>() ;
        resultFile = _resultFile ;
        comment = "" ;
        queryFileSyntax = guessFileSyntax(_queryFile) ;
    }

    public Resource getResource() {
        return testResource ;
    }

    public Resource getAction() {
        return _getAction() ;
    }

    /** @return Returns the testType. */
    public Resource getTestType() {
        return testType ;
    }

    public String getQueryFile() {
        return queryFile ;
    }

    public Syntax getFileSyntax() {
        return queryFileSyntax ;
    }

    public void setFileSyntax(Syntax syntax) {
        queryFileSyntax = syntax ;
    }

    public String getResultFile() {
        return resultFile ;
    }

    /**
     * Load results as a SPARQLResult. If the results are a model, no conversion
     * to a result set is attempted here.
     */
    public SPARQLResult getResults() {
        if ( resultFile == null )
            return null ;
        ResultsFormat format = ResultsFormat.guessSyntax(resultFile) ;

        if ( ResultsFormat.isRDFGraphSyntax(format) ) {
            Model m = FileManager.get().loadModel(resultFile) ;
            return new SPARQLResult(m) ;
        }
        
        if ( ResultsFormat.isDatasetSyntax(format) ) {
            Dataset d = RDFDataMgr.loadDataset(resultFile) ;
            return new SPARQLResult(d) ;
        }

        // Attempt to handle as a resulset or boolean result.s
        SPARQLResult x = ResultSetFactory.result(resultFile) ;
        return x ;
    }

    public String getName() {
        return name ;
    }

    public String getURI() {
        if ( testResource != null && testResource.isURIResource() )
            return testResource.getURI() ;
        return fakeURI() ;
    }

    public String getComment() {
        return comment ;
    }

    public List<String> getDefaultGraphURIs() {
        return defaultGraphURIs ;
    }

    public List<String> getNamedGraphURIs() {
        return namedGraphURIs ;
    }

    public boolean requiresTextIndex() {
        return buildLuceneIndex ;
    }

    // *.rq is strictly SPARQL 1.1 tests.
    protected Syntax guessFileSyntax(String filename) {
        if ( filename.endsWith(".rq") )
            return Syntax.syntaxSPARQL_11;
        if ( filename.endsWith(".ru") )
            return Syntax.syntaxSPARQL_11;
        
        return Syntax.guessFileSyntax(filename);
    }

    private String _getName() {
        
        Statement s = testResource.getProperty(TestManifest.name) ;
        String ln = s.getSubject().getLocalName();
        if ( s == null )
            return ln+" <<unset>>" ;
        return "("+ln+") "+s.getString() ;
    }

    private Resource _getAction() {
        if ( actionResource == null )
            actionResource = testResource.getProperty(TestManifest.action).getResource() ;
        return actionResource ;
    }

    private String _getResultFile() {
        try {
            // It's bnode in some update tests.
            // The Update test code managed building the result.
            return TestUtils.getLiteralOrURI(testResource, TestManifest.result) ;
        } catch (TestException ex) { return null ; }
    }

    private String _getComment() {
        Statement s = testResource.getProperty(RDFS.comment) ;
        if ( s == null )
            return null ;
        return s.getString() ;
    }

    // ----------------------------------------------------
    // ---- Query specific properties

    /**
     * Get the data file (default graph): maybe unknown if part for the query
     * (FROM)
     * 
     * @return List
     */

    private List<String> _getDefaultGraphURIs() {
        if ( !_getAction().isAnon() )
            // Action is a URI - data had better be in the query itself.
            return null ;

        List<String> l = new ArrayList<>() ;
        ClosableIterator<Statement> cIter = _getAction().listProperties(VocabTestQuery.data) ;
        for (; cIter.hasNext();) {
            Statement stmt = cIter.next() ;
            String df = stmt.getResource().getURI() ;
            l.add(df) ;
        }
        cIter.close() ;

        return l ;
    }

    /**
     * Get the named graphs : maybe unknown if part for the query (FROM NAMED)
     * 
     * @return List
     */

    private List<String> _getNamedGraphsURIs() {
        if ( !_getAction().isAnon() )
            // Action is a URI - data had better be in the query itself.
            return null ;

        List<String> l = new ArrayList<>() ;
        ClosableIterator<Statement> cIter = _getAction().listProperties(VocabTestQuery.graphData) ;
        for (; cIter.hasNext();) {
            Statement obj = cIter.next() ;
            String df = obj.getResource().getURI() ;
            l.add(df) ;
        }
        cIter.close() ;

        return l ;
    }

    /**
     * Get the query file: either it is the action (data in query) or it is
     * specified within the bNode as a query/data pair.
     * 
     * @return
     */

    private String _getQueryFile() {
        Resource r = _getAction() ;

        if ( r.hasProperty(VocabTestQuery.query) )
            return TestUtils.getLiteralOrURI(r, VocabTestQuery.query) ;

        // No query property - must be this action node

        if ( _getAction().isAnon() )
            return "[]" ;
        return _getAction().getURI() ;
    }

    private Syntax _getQuerySyntax(Model m, String uri, Syntax def) {
        Resource r = m.createResource(uri) ;
        if ( r.hasProperty(TestManifestX.querySyntax) ) {
            Syntax x = Syntax.make(r.getProperty(TestManifestX.querySyntax).getResource().getURI()) ;
            // System.err.println("Query syntax: "+x) ;
            return x ;
        }

        if ( uri != null ) {
            Syntax synFileName = guessFileSyntax(uri) ;
            if ( synFileName != null )
                return synFileName ;
        }
        return def ;
    }

    private boolean _getTextIndex() {
        Statement s = testResource.getProperty(TestManifestX.textIndex) ;
        if ( s == null )
            return false ;
        return s.getString().equalsIgnoreCase("true") ;
    }

    // ----------------------------------------------------
    // Misc

    @Override
    public String toString() {
        StringBuilder sbuff = new StringBuilder() ;
        String name = getName() ;
        // String actionStr = FmtUtils.stringForRDFNode(_getAction()) ;

        sbuff.append("Name: " + name) ;

        if ( getComment() != null )
            sbuff.append("    Comment: " + getComment()) ;
        return sbuff.toString() ;
    }
}
