/*
 * 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.checkers;

import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.OWL2;
import org.apache.jena.vocabulary.RDF;

import fr.mines_stetienne.ci.saref.SAREFPipelineException;
import fr.mines_stetienne.ci.saref.entities.SAREFTerm;
import fr.mines_stetienne.ci.saref.managers.RepositoryManager;

/**
 * Checks TS 103 673 Clause 9.4.4.1: Term IRI
 * 
 */
public class Clause_9_4_4_1_Checker extends AbstractClauseChecker {

	private static final Pattern PATTERN_LOCAL_NAME = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9]+$");
	private static final Pattern PATTERN_CAMEL_CASE = Pattern.compile("^[A-Z0-9][a-zA-Z0-9]+$");
	private static final Pattern PATTERN_MIXED_CASE = Pattern.compile("^[a-z0-9][a-zA-Z0-9]+$");

	private static enum MESSAGE {
		pattern, classs, namedindividual, objectproperty, datatypeproperty
	}

	public Clause_9_4_4_1_Checker(RepositoryManager repositoryManager) {
		super(repositoryManager, Clause_9_4_4_1_Checker.class);
	}

	private final Set<Resource> termsBadPattern = new HashSet<>();
	private final Set<Resource> classesBadCase = new HashSet<>();
	private final Set<Resource> namedIndividualsBadCase = new HashSet<>();
	private final Set<Resource> objectPropertiesBadCase = new HashSet<>();
	private final Set<Resource> datatypePropertiesBadCase = new HashSet<>();


	@Override
	public void checkClause() throws SAREFPipelineException {
		
		Model model = version.getModel();
		for (SAREFTerm term : version.getDefinedTerms()) {
			String localName = term.getLocalName();
			Resource t = term.getResource();

			if (!PATTERN_LOCAL_NAME.matcher(localName).matches()) {
				termsBadPattern.add(t);
			}
			if (model.contains(t, RDF.type, OWL2.Class) && !PATTERN_CAMEL_CASE.matcher(localName).matches()) {
				classesBadCase.add(t);
			}
			if (model.contains(t, RDF.type, OWL2.NamedIndividual) && !PATTERN_CAMEL_CASE.matcher(localName).matches()) {
				namedIndividualsBadCase.add(t);
			}
			if (model.contains(t, RDF.type, OWL2.ObjectProperty) && !PATTERN_MIXED_CASE.matcher(localName).matches()) {
				objectPropertiesBadCase.add(t);
			}
			if (model.contains(t, RDF.type, OWL2.DatatypeProperty)
					&& !PATTERN_MIXED_CASE.matcher(localName).matches()) {
				datatypePropertiesBadCase.add(t);
			}
		}

		if (!classesBadCase.isEmpty()) {
			logError(getMessage(MESSAGE.classs,
					classesBadCase.stream().map(Object::toString).collect(Collectors.joining(", "))));
		}
		if (!namedIndividualsBadCase.isEmpty()) {
			logError(getMessage(MESSAGE.namedindividual,
					namedIndividualsBadCase.stream().map(Object::toString).collect(Collectors.joining(", "))));
		}
		if (!objectPropertiesBadCase.isEmpty()) {
			logError(getMessage(MESSAGE.objectproperty,
					objectPropertiesBadCase.stream().map(Object::toString).collect(Collectors.joining(", "))));
		}
		if (!datatypePropertiesBadCase.isEmpty()) {
			logError(getMessage(MESSAGE.datatypeproperty,
					datatypePropertiesBadCase.stream().map(Object::toString).collect(Collectors.joining(", "))));
		}
	}

}