/*
 * Copyright 2020 ETSI
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 *    may be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package fr.mines_stetienne.ci.saref;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.file.FileSystems;
import java.nio.file.PathMatcher;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.jena.atlas.RuntimeIOException;
import org.apache.jena.riot.Lang;
import org.slf4j.Logger;

import fr.mines_stetienne.ci.saref.entities.SAREFCore;
import fr.mines_stetienne.ci.saref.entities.SAREFExtension;
import fr.mines_stetienne.ci.saref.entities.SAREFNamedGraph;
import fr.mines_stetienne.ci.saref.entities.SAREFProject;
import fr.mines_stetienne.ci.saref.entities.SAREFVersionName;

/**
*
* @author Maxime Lefrançois
*
*/
public class SAREF {

	public static final PathMatcher TTL_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**/*.ttl");
	public static final PathMatcher CSV_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**/*.csv");

	private final static ResourceBundle BUNDLE = ResourceBundle.getBundle("messages/SAREF");
	public final static String BASE = "https://saref.etsi.org/";
	public final static String FORGE = "https://saref.etsi.org/sources/";
	public final static String LICENSE = "https://forge.etsi.org/etsi-software-license";
	public final static String PUBLISHER = "https://www.etsi.org/";

	public static final String SAREF_PORTAL_STATIC_GIT = "https://labs.etsi.org/rep/saref/saref-portal.git";
	public static final String LOGGER_BASE = "SAREF Pipeline: ";
	
	public static final String NAME_SITE = "site";
	public static final String NAME_SOURCES = "sources";
	public static final String NAME_SOURCES_PORTAL = "portal";

	public static final boolean IGNORE_OOPS = true;
	
	// project acronym
	public static final String REGEX_ACRONYM_VAR = "acronym";
	public static final String REGEX_ACRONYM = String.format("(?<%s>[a-z]{4})", REGEX_ACRONYM_VAR);

	// project name
	public static final String REGEX_NAME_EXTENSION = "saref4" + REGEX_ACRONYM;
	public static final String REGEX_NAME_PROJECT = String.format("(%s|%s)", REGEX_NAME_EXTENSION,
			SAREFCore.INSTANCE.getRepositoryName());

	// project paths
	public static final String REGEX_PATH_CORE = "core";
	public static final String REGEX_PATH_EXTENSION = "saref4" + REGEX_ACRONYM;
	public static final String REGEX_PATH_PROJECT = String.format("(%s|%s)", REGEX_PATH_CORE, REGEX_PATH_EXTENSION);

	// project version
	public static final String REGEX_VERSION_MAJOR_VAR = "major";
	public static final String REGEX_VERSION_MINOR_VAR = "minor";
	public static final String REGEX_VERSION_PATCH_VAR = "patch";
	public static final String REGEX_VERSION_NUMBER = String.format("v(?<%s>[0-9]+)\\.(?<%s>[0-9]+)\\.(?<%s>[0-9]+)", REGEX_VERSION_MAJOR_VAR, REGEX_VERSION_MINOR_VAR, REGEX_VERSION_PATCH_VAR);

	// project version prefix, namespace, ontology IRI, ontology version IRI,
	public static final String REGEX_CORE_PREFIX = "saref";
	public static final String REGEX_EXTENSION_PREFIX = "s4" + REGEX_ACRONYM;

	public static final String REGEX_ONTOLOGY_IRI = String.format("^%s%s/$", BASE, REGEX_PATH_PROJECT);
	public static final String REGEX_ONTOLOGY_VERSION_IRI = String.format("^%s%s/%s/$", BASE, REGEX_PATH_PROJECT,
			REGEX_VERSION_NUMBER);

	// example
	public static final String REGEX_EXAMPLE_NAME_VAR = "examplename";
	public static final String REGEX_EXAMPLE_NAME = String.format("(?<%s>([^/]+))", REGEX_EXAMPLE_NAME_VAR);
	public static final String REGEX_EXAMPLE_FILE_NAME = String.format("^(?<%s>([^/]+))\\.ttl$", REGEX_EXAMPLE_NAME_VAR);

	// example namespace, IRI
	public static final String REGEX_EXAMPLE_IRI = String.format("^%s%s/%s/example/%s#$", BASE, REGEX_PATH_PROJECT,
			REGEX_VERSION_NUMBER, REGEX_EXAMPLE_NAME);
	
	// terms
	public static final String REGEX_TERM_NAME_VAR = "localName";
	public static final String REGEX_TERM_NAME = String.format("(?<%s>[^/]+)", REGEX_TERM_NAME_VAR);
	public static final String REGEX_TERM = String.format("^%s%s/%s$", BASE, REGEX_PATH_PROJECT, REGEX_TERM_NAME);
	
	

	public static SAREFProject extractProject(String uri) {
		final Matcher matcher = Pattern.compile(String.format("^%s%s/", BASE, REGEX_PATH_PROJECT))
				.matcher(uri);
		if (!matcher.find()) {
			return null;
		}
		final String acronym = matcher.group(REGEX_ACRONYM_VAR);
		if (acronym == null) {
			return SAREFCore.INSTANCE;
		} else {
			return new SAREFExtension(acronym);
		}
	}

	public static SAREFVersionName extractVersionName(String uri) {
		final Matcher matcher = Pattern.compile(String.format("^%s%s/%s/", BASE, REGEX_PATH_PROJECT,
				REGEX_VERSION_NUMBER)).matcher(uri);
		if (!matcher.find()) {
			return null;
		}
		int major = Integer.parseInt(matcher.group(REGEX_VERSION_MAJOR_VAR));
		int minor = Integer.parseInt(matcher.group(REGEX_VERSION_MINOR_VAR));
		int patch = Integer.parseInt(matcher.group(REGEX_VERSION_PATCH_VAR));
		return new SAREFVersionName(major, minor, patch);
	}

	public static String extractExampleName(String uri) {
		final Matcher matcher = Pattern.compile(REGEX_EXAMPLE_IRI).matcher(uri);
		if (!matcher.find()) {
			return null;
		}
		return matcher.group(REGEX_EXAMPLE_NAME_VAR);
	}

	public static <T> String getMessage(String key, Object... args) {
		String msg = BUNDLE.getString(key);
		if (args != null) {
			msg = String.format(msg, args);
		}
		return msg;
	}
	

	public static void loadModel(SAREFNamedGraph namedGraph, File file, Logger logger) {
		try (FileInputStream input = new FileInputStream(file)) {
			namedGraph.getModel().read(input, SAREF.BASE, Lang.TTL.getLabel());
		} catch (Exception ex) {
			if (ex instanceof RuntimeIOException && ex.getCause() instanceof MalformedInputException) {
				namedGraph.getModel().removeAll();
				try (InputStreamReader input2 = new InputStreamReader(new FileInputStream(file),
						Charset.defaultCharset())) {
					namedGraph.getModel().read(input2, SAREF.BASE, Lang.TTL.getLabel());
				} catch (Exception ex2) {
					namedGraph.getModel().removeAll();
					String msg = getMessage("turtle", namedGraph.getIRI());
					logger.error(msg, ex2);
				}
			} else {
				String msg = getMessage("turtle", namedGraph.getIRI());
				logger.error(msg, ex);
			}
		}
	}
}
