package eu.dnetlib.efg1914.various.search;

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

import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQExpression;
import javax.xml.xquery.XQSequence;

import net.xqj.sedna.SednaXQDataSource;

import org.apache.log4j.Logger;

import com.xqj2.XQConnection2;

import eu.dnetlib.efg1914.commons.store.XMLStoreException;

public class ExhibitionSearchEngine implements SearchEngine {

    private XQDataSource datasource = new SednaXQDataSource();
    private String dbHost = null;
    private String dbUser = null;
    private String dbPassword = null;
    private String dbName = null;

    private static Logger logger = Logger.getLogger(ExhibitionSearchEngine.class);

    public void init() throws XMLStoreException {
        try {
            logger.info("Connecting to db " + dbName + " on host " + dbHost);
            datasource.setProperty("serverName", dbHost);
            datasource.setProperty("user", dbUser);
            datasource.setProperty("password", dbPassword);
            datasource.setProperty("databaseName", dbName);

        } catch (XQException xqe) {
            throw new
                    XMLStoreException("Failed to initialize the XML store", xqe);
        }
    }

    @Override
    public String getSearchResult(String query) throws ExhibitionSearchEngineException {
        try {
            logger.debug("Executimg query: " + query);

            return evaluateXQuery(query);
        } catch (Exception e) {
            logger.debug("Error getting results.", e);
            throw new ExhibitionSearchEngineException("Error getting results.", e);
        }
    }

    @Override
    public List<String> getSearchResults(String query) throws ExhibitionSearchEngineException {
        List<String> results = new ArrayList<String>();

        XQConnection2 connection;
        try {
            connection = getConnection();

            XQExpression xqe = connection.createExpression();
            XQSequence xqjs = xqe.executeQuery(query);

            while (xqjs.next()) {
                results.add(xqjs.getItemAsString(null));
            }

            connection.close();

        } catch (Exception e) {
            logger.debug("Error getting results.", e);
            throw new ExhibitionSearchEngineException("Error getting results.", e);
        }

        return results;
    }

    private String evaluateXQuery(String xQuery) throws XMLStoreException, XQException {
        XQConnection2 connection = getConnection();

        XQExpression xqe = connection.createExpression();
        XQSequence xqjs = xqe.executeQuery(xQuery);

        String result = xqjs.getSequenceAsString(null);
        logger.debug(result);
        connection.close();

        return result;
    }

    private XQConnection2 getConnection() throws XMLStoreException {
        try {
            return (XQConnection2) datasource.getConnection();

        } catch (XQException xqe) {
            throw new XMLStoreException("Failed to get connection to data source.", xqe);
        }
    }

    public String getDbHost() {
        return dbHost;
    }

    public void setDbHost(String dbHost) {
        this.dbHost = dbHost;
    }

    public String getDbUser() {
        return dbUser;
    }

    public void setDbUser(String dbUser) {
        this.dbUser = dbUser;
    }

    public String getDbPassword() {
        return dbPassword;
    }

    public void setDbPassword(String dbPassword) {
        this.dbPassword = dbPassword;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }
}
