package org.apache.rya.reasoning;

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

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.vocabulary.OWL;
import org.eclipse.rdf4j.model.vocabulary.RDF;

/**
 * Keep track of a single node's types and do reasoning about its types.
 */
public class TypeReasoner extends AbstractReasoner {
    // This node's types, whether asserted or derived
    Map<Resource, Fact> knownTypes = new HashMap<>();

    // Inferences waiting for particular types to be discovered
    Map<Resource, List<Fact>> possibleInferences = new HashMap<>();
    Map<Resource, List<Derivation>> possibleInconsistencies = new HashMap<>();

    /**
     * Constructor.
     * @param   node    Conduct reasoning about/around this node
     * @param   schema  Global schema (class/property) information
     * @param   t       Iteration # of new triples
     * @param   tSchema Iteration # of latest schema change
     */
    public TypeReasoner(Resource node, Schema schema, int t, int tSchema) {
        super(node, schema, t, tSchema);
    }

    /**
     * Process a type (class) assignment from the input. It may have been
     * inferred during a previous iteration.
     * @param typeFact  An assertion about one of this node's types
     */
    void processType(Fact typeFact) {
        Resource type = (Resource) typeFact.getObject();
        boolean newType = !knownTypes.containsKey(type);
        int t = typeFact.getIteration();
        // Save the type in memory unless older knowledge takes precedence
        if (newType || t < knownTypes.get(type).getIteration()) {
            knownTypes.put(type, typeFact);
            // Perform further inference
            typeInference(typeFact);
        }
    }

    /**
     * Produce and process a type derivation from this iteration.
     * TODO: how to implement rules that would produce "literal rdf:type ?x"
     * @param type      The type itself
     * @param rule      The generating rule
     * @param source    The source of the derivation
     */
    void processType(Resource type, OwlRule rule, Fact source) {
        processType(triple(node, RDF.TYPE, type, rule, source));
    }

    /**
     * Infer additional information from a type assertion.
     */
    void typeInference(Fact typeFact) {
        Resource type = (Resource) typeFact.getObject();
        OwlClass c = schema.getClass(type);
        // RL rule cls-nothing2: Inconsistent if type owl:Nothing
        if (OWL.NOTHING.equals(type) && frontier(typeFact)) {
            // Skip if this isn't a new fact
            collectInconsistency(inconsistency(OwlRule.CLS_NOTHING2, typeFact));
        }
        // RL rule cax-dw: type shouldn't be disjointWith a previous type
        Set<Resource> disjoint = c.getDisjointClasses();
        disjoint.retainAll(knownTypes.keySet());
        for (Resource other : disjoint) {
            Fact otherTypeFact = knownTypes.get(other);
            Derivation inc = inconsistency(OwlRule.CAX_DW, typeFact);
            inc.addSource(otherTypeFact);
            collectInconsistency(inc);
        }
        // RL rule cls-com: type shouldn't be complementOf a previous type
        Set<Resource> complementary = c.getComplementaryClasses();
        complementary.retainAll(knownTypes.keySet());
        for (Resource other : complementary) {
            Fact otherTypeFact = knownTypes.get(other);
            Derivation inc = inconsistency(OwlRule.CLS_COM, typeFact);
            inc.addSource(otherTypeFact);
            collectInconsistency(inc);
        }
        // RL rule cax-sco: subClassOf semantics (derive superclasses)
        if (!typeFact.hasRule(OwlRule.CAX_SCO)
            && frontier(typeFact)) {
            // Skip if typeFact itself came from this rule, and/or if typeFact
            // generally shouldn't be the sole source of new information
            for (Resource supertype : c.getSuperClasses()) {
                // If the supertype isn't trivial, assert it
                if (!supertype.equals(type)
                        && !(supertype.equals(OWL.THING))) {
                    processType(supertype, OwlRule.CAX_SCO, typeFact);
                }
            }
        }
        // Apply property restriction rules:
        for (IRI prop : c.getOnProperty()) {
            // RL rule cls-hv1: if type is an owl:hasValue restriction
            for (Value val : c.hasValue()) {
                collect(triple(node, prop, val, OwlRule.CLS_HV1, typeFact));
            }
        }
        // Derive any facts whose explicit condition is this type assignment
        if (possibleInferences.containsKey(type)) {
            for (Fact fact : possibleInferences.get(type)) {
                Fact join = fact.clone();
                join.addSource(typeFact);
                collect(join);
            }
        }
        // Derive any inconsistencies whose explicit condition is this type
        if (possibleInconsistencies.containsKey(type)) {
            for (Derivation d : possibleInconsistencies.get(type)) {
                Derivation inc = d.clone();
                inc.addSource(typeFact);
                collectInconsistency(inc);
            }
        }
    }

    /**
     * Assert an arbitrary fact if and when this node is determined to have
     * a particular type. Facilitates join rules specifically concerning type.
     */
    void onType(Resource type, Fact fact) {
        if (!possibleInferences.containsKey(type)) {
            possibleInferences.put(type, new LinkedList<Fact>());
        }
        possibleInferences.get(type).add(fact);
        // If we already know the type, assert the fact right away.
        if (knownTypes.containsKey(type)) {
            Fact join = fact.clone();
            join.addSource(knownTypes.get(type));
            collect(join);
        }
    }

    /**
     * Assert an inconsistency if and when this node is determined to have
     * a particular type. Facilitates join rules specifically concerning type.
     */
    void inconsistentOnType(Resource type, Derivation fact) {
        if (!possibleInconsistencies.containsKey(type)) {
            possibleInconsistencies.put(type, new LinkedList<Derivation>());
        }
        possibleInconsistencies.get(type).add(fact);
        // If we already know the type, assert the fact right away.
        if (knownTypes.containsKey(type)) {
            Derivation d = fact.clone();
            d.addSource(knownTypes.get(type));
            collectInconsistency(d);
        }
    }

    /**
     * Collect all the type knowledge into the output, if it represents new
     * information.
     */
    void collectTypes() {
        for (Resource type : knownTypes.keySet()) {
            collect(knownTypes.get(type));
        }
    }

    /**
     * Get info about types derived and potential inferences.
     */
    @Override
    public String getDiagnostics() {
        int total = 0;
        int incTotal = 0;
        for (Resource iri : possibleInferences.keySet()) {
            total += possibleInferences.get(iri).size();
        }
        for (Resource iri : possibleInconsistencies.keySet()) {
            incTotal += possibleInconsistencies.get(iri).size();
        }
        StringBuilder sb = new StringBuilder();
        sb.append(knownTypes.size()).append(" total types known\n");
        sb.append("Watching for ").append(possibleInferences.size());
        sb.append(" distinct types to trigger any of ").append(total);
        sb.append(" possible inferences");
        sb.append("Watching for ").append(possibleInconsistencies.size());
        sb.append(" distinct types to trigger any of ").append(incTotal);
        sb.append(" possible inconsistencies");
        return sb.toString();
    }

    /**
     * Get the total number of input facts cached.
     */
    @Override
    public int getNumStored() {
        int total = knownTypes.size();
        for (List<Fact> l : possibleInferences.values()) {
            total += l.size();
        }
        for (List<Derivation> l : possibleInconsistencies.values()) {
            total += l.size();
        }
        return total;
    }
}
