/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.etsi.saref.server.entities;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdfconnection.RDFConnection;
import org.apache.jena.rdfconnection.RDFConnectionFactory;
import org.etsi.saref.server.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author maxime.lefrancois
 */
public class VersionManager {

    private static final Logger LOG = LoggerFactory.getLogger(VersionManager.class);
    private static final String REGEX = "https://saref.etsi.org/%s/v(?<major>[1-9][0-9]*)\\.(?<minor>[0-9]+)\\.(?<patch>[0-9]+)/$";
    private static final String queryPattern = "PREFIX ex: <http://example.org/>\n"
            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
            + "SELECT ?v\n"
            + "FROM <http://example.org/config>\n"
            + "WHERE {\n"
            + "  \n"
            + "  <https://saref.etsi.org/%s/> ex:hasVersion ?v .\n"
            + "}";

    public static List<Version> getVersions(String ontology) {
        final List<Version> versions = new ArrayList<>();
        try (RDFConnection conn = RDFConnectionFactory.connect(Utils.DS)) {
            String query = String.format(queryPattern, ontology);
            try (QueryExecution exec = conn.query(query)) {
                ResultSet select = exec.execSelect();
                select.forEachRemaining(sol -> {
                    RDFNode node = sol.get("v");
                    if (node == null || !node.isURIResource()) {
                        return;
                    }
                    Pattern patternVersion = Pattern.compile(String.format(REGEX, ontology));
                    Matcher m = patternVersion.matcher(node.asResource().getURI());
                    if (!m.find()) {
                        return;
                    }
                    Version version = new Version();
                    version.major = Integer.parseInt(m.group("major"));
                    version.minor = Integer.parseInt(m.group("minor"));
                    version.patch = Integer.parseInt(m.group("patch"));
                    versions.add(version);
                });
            } catch (Exception ex) {
                LOG.warn("ex", ex);
            }
        } catch (Exception ex) {
            LOG.warn("ex", ex);
        }
        Collections.sort(versions, (Version o1, Version o2) -> {
            if (o1.major - o2.major != 0) {
                return o1.major - o2.major;
            }
            if (o1.minor - o2.minor != 0) {
                return o1.minor - o2.minor;
            }
            return o1.patch - o2.patch;
        });
        return versions;
    }

    public static Version getBestChoice(String ontology, Version req) {
        List<Version> versions = getVersions(ontology);
        Version res = null;
        for (Version version : versions) {
            if (req.major != -1 && version.major != req.major) {
                continue;
            }
            if (req.minor != -1 && version.minor != req.minor) {
                continue;
            }
            if (req.patch != -1 && version.patch != req.patch) {
                continue;
            }
            res = version;
        }
        return res;
    }
}
