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.HashSet;
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.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.vocabulary.OWL;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;

/**
 * Hold on to facts about the schema (TBox/RBox) and perform what reasoning we
 * can without instance data.
 * <p>
 * The Schema object, together with the OwlClass and OwlProperty objects it
 * keeps track of, is responsible for schema reasoning, or the "Semantics of
 * Schema Vocabulary" rules from the OWL RL/RDF specificiation. Some rules are
 * handled dynamically, while the rest must be computed by calling closure()
 * once the schema data has been read in.
 * <p>
 * Schema rules implemented in {@link OwlClass}:
 *      scm-cls, scm-eqc1, scm-eqc2, scm-sco,
 *      scm-hv, scm-svf2, scm-avf2
 * <p>
 * Schema rules implemented in {@link OwlProperty}:
 *      scm-op, scm-dp, scm-eqp1, scm-eqp2, scm-spo, scm-dom1, scm-dom2,
 *      scm-rng1, scm-rng2, scm-svf1, scm-avf1
 * <p>
 * TODO: scm-cls officially states owl:Nothing is a subclass of every class.
 *  Do we need to explicitly do something with this fact?
 */
public class Schema {
    // Statements using these predicates are automatically relevant schema
    // information.
    private static final Set<IRI> schemaPredicates = new HashSet<>();
    private static final IRI[] schemaPredicateURIs = {
        RDFS.SUBCLASSOF,
        RDFS.SUBPROPERTYOF,
        RDFS.DOMAIN,
        RDFS.RANGE,
        OWL.EQUIVALENTCLASS,
        OWL.EQUIVALENTPROPERTY,
        OWL.INVERSEOF,
        OWL.DISJOINTWITH,
        OWL.COMPLEMENTOF,
        OWL.ONPROPERTY,
        OWL.SOMEVALUESFROM,
        OWL.ALLVALUESFROM,
        OWL.HASVALUE,
        OWL.MAXCARDINALITY,
        OWL2.MAXQUALIFIEDCARDINALITY,
        OWL2.PROPERTYDISJOINTWITH,
        OWL2.ONCLASS
    };

    // The fact that something is one of these types is schema information.
    private static final Set<Resource> schemaTypes = new HashSet<>();
    private static final Resource[] schemaTypeURIs = {
        OWL.TRANSITIVEPROPERTY,
        OWL2.IRREFLEXIVEPROPERTY,
        OWL.SYMMETRICPROPERTY,
        OWL2.ASYMMETRICPROPERTY,
        OWL.FUNCTIONALPROPERTY,
        OWL.INVERSEFUNCTIONALPROPERTY
    };

    static {
        for (IRI iri : schemaPredicateURIs) {
            schemaPredicates.add(iri);
        }
        for (Resource iri : schemaTypeURIs) {
            schemaTypes.add(iri);
        }
    }

    /**
     * Does this triple/statement encode potentially relevant schema
     * information?
     */
    public static boolean isSchemaTriple(Statement triple) {
        IRI pred = triple.getPredicate();
        // Triples with certain predicates are schema triples,
        if (schemaPredicates.contains(pred)) {
            return true;
        }
        // And certain type assertions are schema triples.
        else if (pred.equals(RDF.TYPE)) {
            if (schemaTypes.contains(triple.getObject())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Map URIs to schema information about a property
     */
    protected Map<IRI, OwlProperty> properties = new HashMap<>();

    /**
     * Map Resources to schema information about a class/restriction
     */
    protected Map<Resource, OwlClass> classes = new HashMap<>();

    /**
     * Get schema information for a class, for reading and writing.
     * Instantiates OwlClass if it doesn't yet exist.
     */
    public OwlClass getClass(Resource c) {
        if (!classes.containsKey(c)) {
            classes.put(c, new OwlClass(c));
        }
        return classes.get(c);
    }

    /**
     * Get schema information for a class, for reading and writing.
     * Assumes this Value refers to a class Resource.
     */
    public OwlClass getClass(Value c) {
        return getClass((Resource) c);
    }

    /**
     * Get schema information for a property, for reading and writing.
     * Instantiates OwlProperty if it doesn't yet exist.
     */
    public OwlProperty getProperty(IRI p) {
        if (!properties.containsKey(p)) {
            properties.put(p, new OwlProperty(p));
        }
        return properties.get(p);
    }

    /**
     * Get schema information for a property, for reading and writing.
     * Assumes this Value refers to a property URI.
     */
    public OwlProperty getProperty(Value p) {
        return getProperty((IRI) p);
    }

    /**
     * Return whether this resource corresponds to a property.
     */
    public boolean hasProperty(IRI r) {
        return properties.containsKey(r);
    }

    /**
     * Return whether this resource corresponds to a class.
     */
    public boolean hasClass(Resource r) {
        return classes.containsKey(r);
    }

    /**
     * Return whether this resource corresponds to a property restriction.
     */
    public boolean hasRestriction(Resource r) {
        return classes.containsKey(r) && !classes.get(r).getOnProperty().isEmpty();
    }

    public Schema() {
    }

    /**
     * Incorporate a new triple into the schema.
     */
    public void processTriple(Statement triple) {
        Resource s = triple.getSubject();
        IRI p = triple.getPredicate();
        Value o = triple.getObject();
        if (isSchemaTriple(triple)) {
            // For a type statement to be schema information, it must yield
            // some boolean information about a property.
            if (p.equals(RDF.TYPE)) {
                if (schemaTypes.contains(o)) {
                    addPropertyType((IRI) s, (Resource) o);
                }
            }

            // Domain/range
            else if (p.equals(RDFS.DOMAIN)) {
                // Don't add trivial domain owl:Thing
                if (!o.equals(OWL.THING)) {
                    getProperty(s).addDomain(getClass(o));
                }
            }
            else if (p.equals(RDFS.RANGE)) {
                // Don't add trivial range owl:Thing
                if (!o.equals(OWL.THING)) {
                    getProperty(s).addRange(getClass(o));
                }
            }

            // Sub/super relations
            else if (p.equals(RDFS.SUBCLASSOF)) {
                // Everything is a subclass of owl#Thing, we don't need to
                // store that information
                if (!o.equals(OWL.THING)) {
                    getClass(s).addSuperClass(getClass(o));
                }
            }
            else if (p.equals(RDFS.SUBPROPERTYOF)) {
                getProperty(s).addSuperProperty(getProperty(o));
            }

            // Equivalence relations
            else if (p.equals(OWL.EQUIVALENTCLASS)) {
                getClass(s).addEquivalentClass(getClass(o));
            }
            else if (p.equals(OWL.EQUIVALENTPROPERTY)) {
                getProperty(s).addEquivalentProperty(getProperty(o));
            }

            // Inverse properties
            else if (p.equals(OWL.INVERSEOF)) {
                getProperty(s).addInverse(getProperty(o));
                getProperty(o).addInverse(getProperty(s));
            }

            // Complementary classes
            else if (p.equals(OWL.COMPLEMENTOF)) {
                getClass(s).addComplement(getClass(o));
                getClass(o).addComplement(getClass(s));
            }

            // Disjoint classes and properties
            else if (p.equals(OWL.DISJOINTWITH)) {
                getClass(s).addDisjoint(getClass(o));
                getClass(o).addDisjoint(getClass(s));
            }
            else if (p.equals(OWL2.PROPERTYDISJOINTWITH)) {
                getProperty(s).addDisjoint(getProperty(o));
                getProperty(o).addDisjoint(getProperty(s));
            }

            // Property restriction info
            else if (p.equals(OWL.ONPROPERTY)) {
                getClass(s).addProperty(getProperty(o));
            }
            else if (p.equals(OWL.SOMEVALUESFROM)) {
                getClass(s).addSvf(getClass(o));
            }
            else if (p.equals(OWL.ALLVALUESFROM)) {
                getClass(s).addAvf(getClass(o));
            }
            else if (p.equals(OWL2.ONCLASS)) {
                getClass(s).addClass(getClass(o));
            }
            else if (p.equals(OWL.HASVALUE)) {
                getClass(s).addValue(o);
            }
            else if (p.equals(OWL.MAXCARDINALITY)) {
                getClass(s).setMaxCardinality(o);
            }
            else if (p.equals(OWL2.MAXQUALIFIEDCARDINALITY)) {
                getClass(s).setMaxQualifiedCardinality(o);
            }
        }
    }

    /**
     * Add a particular characteristic to a property.
     */
    private void addPropertyType(IRI p, Resource t) {
        OwlProperty prop = getProperty(p);
        if (t.equals(OWL.TRANSITIVEPROPERTY)) {
            prop.setTransitive();
        }
        else if (t.equals(OWL.SYMMETRICPROPERTY)) {
            prop.setSymmetric();
        }
        else if (t.equals(OWL2.ASYMMETRICPROPERTY)) {
            prop.setAsymmetric();
        }
        else if (t.equals(OWL.FUNCTIONALPROPERTY)) {
            prop.setFunctional();
        }
        else if (t.equals(OWL.INVERSEFUNCTIONALPROPERTY)) {
            prop.setInverseFunctional();
        }
        else if (t.equals(OWL2.IRREFLEXIVEPROPERTY)) {
            prop.setIrreflexive();
        }
    }

    /**
     * Perform schema-level reasoning to compute the closure of statements
     * already represented in this schema. This includes things like subClassOf
     * transitivity and applying domain/range to subclasses.
     */
    public void closure() {
        // RL rule scm-spo: subPropertyOf transitivity
        // (takes in subproperty info; yields subproperty info)
        for (OwlProperty subprop : properties.values()) {
            subprop.computeSuperProperties();
        }

        // RL rules scm-hv, scm-svf2, scm-avf2: restrictions & subproperties
        // (take in subproperty info & prop. restrictions; yield subclass info)
        for (OwlClass c1 : classes.values()) {
            for (OwlClass c2 : classes.values()) {
                c1.compareRestrictions(c2);
            }
        }

        // The following two steps can affect each other, so repeat the block
        // as many times as necessary.
        boolean repeat;
        do {
            // RL rule scm-sco: subClassOf transitivity
            // (takes in subclass info; yields subclass info)
            // (This traverses the complete hierarchy, so we don't need to loop
            // again if changes are only made in this step)
            for (OwlClass subclass : classes.values()) {
                subclass.computeSuperClasses();
            }
            // RL rules scm-svf1, scm-avf1: property restrictions & subclasses
            // (take in subclass info & prop. restrictions; yield subclass info)
            // (If changes are made here, loop through both steps again)
            repeat = false;
            for (OwlProperty prop : properties.values()) {
                repeat = prop.compareRestrictions() || repeat;
            }
        } while (repeat);

        // Apply RL rules scm-dom1, scm-rng1, scm-dom2, scm-rng2:
        // (take in subclass/subproperty & domain/range; yield domain/range)
        for (OwlProperty prop : properties.values()) {
            prop.inheritDomainRange();
        }
    }

    /**
     * Determine whether a fact is contained in the Schema object
     * relationships or implied by schema rules.
     * @return  True if this schema contains the semantics of the triple
     */
    public boolean containsTriple(Statement triple) {
        // The schema certainly doesn't contain it if it's not a
        // schema-relevant triple at all.
        if (isSchemaTriple(triple)) {
            Resource s = triple.getSubject();
            IRI p = triple.getPredicate();
            Value o = triple.getObject();
            // If this is telling us something about a property:
            if (properties.containsKey(s)) {
                OwlProperty prop = properties.get(s);
                // Property types:
                if (p.equals(RDF.TYPE)) {
                    if ((o.equals(OWL.TRANSITIVEPROPERTY)
                            && prop.isTransitive())
                        || (o.equals(OWL2.IRREFLEXIVEPROPERTY)
                            && prop.isIrreflexive())
                        || (o.equals(OWL.SYMMETRICPROPERTY)
                            && prop.isSymmetric())
                        || (o.equals(OWL2.ASYMMETRICPROPERTY)
                            && prop.isAsymmetric())
                        || (o.equals(OWL.FUNCTIONALPROPERTY)
                            && prop.isFunctional())
                        || (o.equals(OWL.INVERSEFUNCTIONALPROPERTY)
                            && prop.isInverseFunctional())) {
                        return true;
                    }
                }
                // Relationships with other properties:
                if ((p.equals(RDFS.SUBPROPERTYOF)
                        && prop.getSuperProperties().contains(o))
                    || (p.equals(OWL2.PROPERTYDISJOINTWITH)
                        && prop.getDisjointProperties().contains(o))
                    || (p.equals(OWL.EQUIVALENTPROPERTY)
                        && prop.getEquivalentProperties().contains(o))
                    || (p.equals(OWL.INVERSEOF)
                        && prop.getInverseProperties().contains(o))) {
                    return true;
                }
                // Relationships with classes:
                if ((p.equals(RDFS.DOMAIN)
                        && prop.getDomain().contains(o))
                    || (p.equals(RDFS.RANGE)
                        && prop.getRange().contains(o))) {
                    return true;
                }
            }
            // If this is about a class relationship:
            if (classes.containsKey(s)) {
                OwlClass subject = classes.get(s);
                if ((p.equals(OWL.EQUIVALENTCLASS)
                        && (subject.getEquivalentClasses().contains(o)))
                    || (p.equals(OWL.DISJOINTWITH)
                        && (subject.getDisjointClasses().contains(o)))
                    || (p.equals(OWL.COMPLEMENTOF)
                        && (subject.getComplementaryClasses().contains(o)))
                    || (p.equals(RDFS.SUBCLASSOF)
                        && (subject.getSuperClasses().contains(o)))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Collect and return counts of different kinds of schema constructs
     */
    public String getSummary() {
        int nRestrictions = 0;
        for (Resource r : classes.keySet()) {
            OwlClass c = classes.get(r);
            if (!c.getOnProperty().isEmpty()) {
                nRestrictions++;
            }
        }
        int nClasses = classes.size();
        int nProperties = properties.size();
        String[] pTypes = { "Transitive", "Symmetric", "Asymmetric",
            "Functional", "Inverse Functional", "Irreflexive" };
        String[] rTypes = { "someValuesFrom", "allValuesFrom", "hasValue",
            "maxCardinality==0", "maxCardinality>0",
            "maxQualifiedCardinality==0", "maxQualifiedCardinality>0", };
        String[] edgeTypes = { "Superclass", "Disjoint class", "Complement",
            "Superproperty", "Disjoint property", "Inverse property",
            "Domain", "Range",
            "Equivalent class", "Equivalent property"};
        int[] pTotals = { 0, 0, 0, 0, 0, 0 };
        int[] rTotals = { 0, 0, 0, 0, 0, 0, 0 };
        int[] edgeTotals = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        for (OwlClass c : classes.values()) {
            edgeTotals[0] += c.getSuperClasses().size() - 2;
            edgeTotals[1] += c.getDisjointClasses().size();
            edgeTotals[2] += c.getComplementaryClasses().size();
            edgeTotals[8] += c.getEquivalentClasses().size() - 1;
            if (!c.someValuesFrom().isEmpty()) rTotals[0]++;
            if (!c.allValuesFrom().isEmpty()) rTotals[1]++;
            if (!c.hasValue().isEmpty()) rTotals[2]++;
            if (c.getMaxCardinality() == 0) rTotals[3]++;
            if (c.getMaxCardinality() > 0) rTotals[4]++;
            if (c.getMaxQualifiedCardinality() == 0) rTotals[5]++;
            if (c.getMaxQualifiedCardinality() > 0) rTotals[6]++;
        }
        for (OwlProperty p : properties.values()) {
            if (p.isTransitive()) pTotals[0]++;
            if (p.isSymmetric()) pTotals[1]++;
            if (p.isAsymmetric()) pTotals[2]++;
            if (p.isFunctional()) pTotals[3]++;
            if (p.isInverseFunctional()) pTotals[4]++;
            if (p.isIrreflexive()) pTotals[5]++;
            edgeTotals[3] += p.getSuperProperties().size() - 1;
            edgeTotals[4] += p.getDisjointProperties().size();
            edgeTotals[5] += p.getInverseProperties().size();
            edgeTotals[6] += p.getDomain().size();
            edgeTotals[7] += p.getRange().size();
            edgeTotals[9] += p.getEquivalentProperties().size();
        }
        StringBuilder sb = new StringBuilder();
        sb.append("Schema summary:");
        sb.append("\n\tClasses: " + nClasses);
        sb.append("\n\t\tProperty Restrictions: ").append(nRestrictions);
        for (int i = 0; i < rTypes.length; i++) {
            sb.append("\n\t\t\t");
            sb.append(rTypes[i]).append(": ").append(rTotals[i]);
        }
        sb.append("\n\t\tOther: ").append(nClasses-nRestrictions);
        sb.append("\n\tProperties: ").append(nProperties);
        for (int i = 0; i < pTypes.length; i++) {
            sb.append("\n\t\t");
            sb.append(pTypes[i]).append(": ").append(pTotals[i]);
        }
        sb.append("\n\tConnections:");
        for (int i = 0; i < edgeTypes.length; i++) {
            sb.append("\n\t\t");
            sb.append(edgeTypes[i]).append(": ").append(edgeTotals[i]);
        }
        return sb.toString();
    }

    /**
     * Assuming a given resource corresponds to a property restriction,
     * describe the restriction.
     */
    public String explainRestriction(Resource type) {
        StringBuilder sb = new StringBuilder();
        if (classes.containsKey(type)) {
            OwlClass pr = classes.get(type);
            sb.append("owl:Restriction");
            for (IRI p : pr.getOnProperty()) {
                sb.append(" (owl:onProperty ").append(p.toString()).append(")");
            }
            for (Value v : pr.hasValue()) {
                sb.append(" (owl:hasValue ").append(v.toString()).append(")");
            }
            for (Resource c : pr.someValuesFrom()) {
                sb.append(" (owl:someValuesFrom ").append(c.toString()).append(")");
            }
            for (Resource c : pr.allValuesFrom()) {
                sb.append(" (owl:allValuesFrom ").append(c.toString()).append(")");
            }
            int mc = pr.getMaxCardinality();
            int mqc = pr.getMaxQualifiedCardinality();
            if (mc >= 0) {
                sb.append(" (owl:maxCardinality ").append(mc).append(")");
            }
            if (mqc >= 0) {
                sb.append(" (owl:maxQualifiedCardinality ").append(mqc);
            }
            for (Resource c : pr.onClass()) {
                sb.append(" owl:onClass ").append(c.toString()).append(")");
            }
        }
        return sb.toString();
    }
}
