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.io.Serializable;
import java.util.HashSet;
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;

/**
 * Contains all the schema information we might need about a class.
 * <p>
 * Rules applied dynamically by getter methods:
 * <ul>
 * <li>
 * scm-cls  States that every class is its own subclass and equivalent class,
 *          and is a subclass of owl:Thing. These facts are included by
 *          getSuperClasses and getEquivalentClasses. (It also states that
 *          owl:Nothing is a subclass of every class).
 * <li>
 * scm-eqc1 States that if two classes are equivalent, they are also
 *          subclasses. Equivalence is represented using subclass relations
 *          internally.
 * <li>
 * scm-eqc2 States that if two classes are each other's subclasses, they are
 *          also equivalent classes.
 * </ul>
 * Rules applied by explicitly calling methods once all data has been read in:
 * <ul>
 * <p>
 * <li>
 * scm-sco  States that subClassOf is transitive. Computed by
 *          computeSuperClasses().
 * </ul>
 */
public class OwlClass implements Serializable {
    private static final long serialVersionUID = 1L;
    private Resource iri;

    // Relations to other classes:
    private Set<OwlClass> superClasses = new HashSet<>();
    private Set<OwlClass> disjointClasses = new HashSet<>();
    private Set<OwlClass> complementaryClasses = new HashSet<>();

    // If this class is referenced by property restrictions:
    private Set<OwlClass> svfRestrictions = new HashSet<>();
    private Set<OwlClass> avfRestrictions = new HashSet<>();
    private Set<OwlClass> qcRestrictions = new HashSet<>();

    // If this is a property restriction, Which propert(y/ies) does it apply to?
    Set<OwlProperty> properties = new HashSet<OwlProperty>();
    // These represent the semantics of the restriction:
    Set<OwlClass> svfClasses = new HashSet<>();
    Set<OwlClass> avfClasses = new HashSet<>();
    Set<OwlClass> qcClasses = new HashSet<>();
    Set<Value> values = new HashSet<>();
    int maxCardinality = -1;
    int maxQualifiedCardinality = -1;

    OwlClass(Resource iri) {
        this.iri = iri;
    }

    public Resource getURI() { return iri; }
    public void setURI(Resource iri) { this.iri = iri; }

    /**
     * Add a superclass
     */
    boolean addSuperClass(OwlClass c) {
        return superClasses.add(c);
    }

    /**
     * Add an equivalent class
     * RL rule scm-eqc1: Store equivalence as mutual subClassOf relations
     */
    boolean addEquivalentClass(OwlClass c) {
        boolean change = superClasses.add(c);
        change = c.superClasses.add(this) || change;
        return change;
    }
    /**
     * Add a disjoint class
     */
    boolean addDisjoint(OwlClass c) { return disjointClasses.add(c); }
    /**
     * Add a complementary class
     */
    boolean addComplement(OwlClass c) { return complementaryClasses.add(c); }
    /**
     * Add a someValuesFrom restriction on this class
     */
    boolean addSvfRestriction(OwlClass r) { return svfRestrictions.add(r); }
    /**
     * Add an allValuesFrom restriction on this class
     */
    boolean addAvfRestriction(OwlClass r) { return avfRestrictions.add(r); }
    /**
     * Add a qualified cardinality restriction on this class
     */
    boolean addQCRestriction(OwlClass r) { return qcRestrictions.add(r); }

    /**
     * Apply RL rule scm-sco: subClassOf transitivity.
     * Follows subClassOf chains to compute all the ancestor classes. Assumes
     * the hierarchy is small enough that a simple BFS is fine.
     * @return  Whether new information was discovered
     */
    boolean computeSuperClasses() {
        Set<OwlClass> ancestors = new HashSet<OwlClass>();
        Set<OwlClass> frontier = new HashSet<OwlClass>(superClasses);
        while (!frontier.isEmpty()) {
            Set<OwlClass> next = new HashSet<OwlClass>();
            for (OwlClass ancestor : frontier) {
                // This node is an ancestor; it's parents should be explored next
                ancestors.add(ancestor);
                next.addAll(ancestor.superClasses);
            }
            // Don't revisit nodes
            next.removeAll(ancestors);
            frontier = next;
        }
        boolean newInfo = !ancestors.equals(superClasses);
        superClasses = ancestors;
        return newInfo;
    }

    /**
     * Add all of this class' ancestors to the domain of a given property.
     */
    void inheritDomains(OwlProperty prop) {
        for (OwlClass superclass : this.superClasses) {
            prop.addDomain(superclass);
        }
    }

    /**
     * Add all of this class' ancestors to the range of a given property.
     */
    void inheritRanges(OwlProperty prop) {
        for (OwlClass superclass : this.superClasses) {
            prop.addRange(superclass);
        }
    }

    /**
     * Add "onProperty p" information, and tell p to point back here.
     */
    public boolean addProperty(OwlProperty property) {
        property.addRestriction(this);
        return properties.add(property);
    }

    /**
     * Add "someValuesFrom c" information, and tell c to point back here.
     */
    public boolean addSvf(OwlClass targetClass) {
        targetClass.addSvfRestriction(this);
        return svfClasses.add(targetClass);
    }

    /**
     * Add "allValuesFrom c" information, and tell c to point back here.
     */
    public boolean addAvf(OwlClass targetClass) {
        targetClass.addAvfRestriction(this);
        return avfClasses.add(targetClass);
    }

    /**
     * Add "onClass c" information, and tell c to point back here.
     */
    public boolean addClass(OwlClass targetClass) {
        targetClass.addQCRestriction(this);
        return qcClasses.add(targetClass);
    }

    /**
     * Add "hasValue v" information.
     */
    public boolean addValue(Value v) {
        return values.add(v);
    }

    /**
     * Set a maxCardinality.
     */
    public boolean setMaxCardinality(Value v) {
        int mc = Integer.parseInt(v.stringValue());
        if (maxCardinality < 0 || mc < maxCardinality) {
            maxCardinality = mc;
            return true;
        }
        return false;
    }

    /**
     * Set maxQualifiedCardinality.
     */
    public boolean setMaxQualifiedCardinality(Value v) {
        int mqc = Integer.parseInt(v.stringValue());
        if (maxQualifiedCardinality < 0 || mqc < maxQualifiedCardinality) {
            maxQualifiedCardinality = mqc;
            return true;
        }
        return false;
    }


    /**
     * Get all the superclasses of this subclass. Includes self and owl:Thing.
     */
    public Set<Resource> getSuperClasses() {
        Set<Resource> ancestors = new HashSet<>();
        for (OwlClass ancestor : superClasses) {
            ancestors.add(ancestor.iri);
        }
        // RL rule scm-cls: Every class is a subclass of itself and owl:Thing
        ancestors.add(this.iri);
        ancestors.add(OWL.THING);
        return ancestors;
    }

    /**
     * Get all the equivalent classes, meaning those who are both subclasses
     * and superclasses of this one.
     */
    public Set<Resource> getEquivalentClasses() {
        // RL rule scm-eqc2: mutual subClassOf relations imply equivalentClass
        Set<Resource> equivalents = new HashSet<>();
        for (OwlClass other : superClasses) {
            if (other.superClasses.contains(this)) {
                equivalents.add(other.iri);
            }
        }
        // RL rule scm-cls: Every class is its own equivalent
        equivalents.add(this.iri);
        return equivalents;
    }

    /**
     * Get all classes declared disjoint with this one.
     */
    public Set<Resource> getDisjointClasses() {
        Set<Resource> disjoint = new HashSet<>();
        for (OwlClass other : disjointClasses) {
            disjoint.add(other.iri);
        }
        return disjoint;
    }

    /**
     * Get all classes declared complement to a specific class.
     */
    public Set<Resource> getComplementaryClasses() {
        Set<Resource> complements = new HashSet<>();
        for (OwlClass other : complementaryClasses) {
            complements.add(other.iri);
        }
        return complements;
    }

    /**
     * Get all someValuesFrom restrictions on this class
     */
    public Set<Resource> getSvfRestrictions() {
        Set<Resource> restrictions = new HashSet<>();
        for (OwlClass r : svfRestrictions) {
            restrictions.add(r.getURI());
        }
        return restrictions;
    }

    /**
     * Get all allValuesFrom restrictions on this class
     */
    public Set<Resource> getAvfRestrictions() {
        Set<Resource> restrictions = new HashSet<>();
        for (OwlClass r : avfRestrictions) {
            restrictions.add(r.getURI());
        }
        return restrictions;
    }

    /**
     * Get all onClass (qualified cardinality) restrictions on this class
     */
    public Set<Resource> getQCRestrictions() {
        Set<Resource> restrictions = new HashSet<>();
        for (OwlClass r : qcRestrictions) {
            restrictions.add(r.getURI());
        }
        return restrictions;
    }

    /**
     * Get the onProperty relation(s) for this property restriction.
     */
    public Set<IRI> getOnProperty() {
        Set<IRI> onp = new HashSet<>();
        for (OwlProperty prop : properties) {
            onp.add(prop.getURI());
        }
        return onp;
    }

    /**
     * Get all someValuesFrom relations for this property restriction.
     */
    public Set<Resource> someValuesFrom() {
        Set<Resource> targets = new HashSet<>();
        for (OwlClass c : svfClasses) {
            targets.add(c.getURI());
        }
        return targets;
    }

    /**
     * Get all allValuesFrom relations for this property restriction.
     */
    public Set<Resource> allValuesFrom() {
        Set<Resource> targets = new HashSet<>();
        for (OwlClass c : avfClasses) {
            targets.add(c.getURI());
        }
        return targets;
    }

    /**
     * Get all onClass relations for this property restriction.
     */
    public Set<Resource> onClass() {
        Set<Resource> targets = new HashSet<>();
        for (OwlClass c : qcClasses) {
            targets.add(c.getURI());
        }
        return targets;
    }

    /**
     * Get all hasValue relations for this property restriction.
     */
    public Set<Value> hasValue() { return new HashSet<Value>(values); }

    /**
     * Get the maxCardinality. Negative means it was not specified, otherwise
     * returns the lowest value ever given.
     */
    public int getMaxCardinality() { return maxCardinality; }

    /**
     * Get the maxQualifiedCardinality. Negative means it was not specified,
     * otherwise returns the lowest value ever given.
     */
    public int getMaxQualifiedCardinality() { return maxQualifiedCardinality; }

    /**
     * Compares someValuesFrom target classes, and returns true if this one's
     * is a subclass of the other's.
     */
    boolean svfSubClass(OwlClass other) {
        for (OwlClass svfClass : this.svfClasses) {
            Set<Resource> intersection = svfClass.getSuperClasses();
            intersection.retainAll(other.someValuesFrom());
            if (!intersection.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Compares someValuesFrom target classes, and returns true if this one's
     * is a subclass of the other's.
     */
    boolean avfSubClass(OwlClass other) {
        for (OwlClass avfClass : this.avfClasses) {
            Set<Resource> intersection = avfClass.getSuperClasses();
            intersection.retainAll(other.allValuesFrom());
            if (!intersection.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Compares onProperty properties, and returns true if this one's
     * is a subproperty of the other's.
     */
    boolean onSubProperty(OwlClass other) {
        Set<IRI> otherProp = other.getOnProperty();
        for (OwlProperty prop : this.properties) {
            Set<IRI> intersection = prop.getSuperProperties();
            intersection.retainAll(otherProp);
            if (!intersection.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Apply property restriction rules that involve the same class/value
     * and properties related by subPropertyOf.
     * RL rule scm-hv: [subprop hasValue] subClassOf [superprop hasValue]
     * RL rule scm-svf2: [subprop someValuesFrom x] subClassOf [superprop someValuesFrom x]
     * RL rule scm-avf2: [superprop allValuesFrom x] subClassOf [subprop allValuesFrom x]
     * Doesn't check subproperty transitivity.
     * @return  Whether any information was generated
     */
    boolean compareRestrictions(OwlClass other) {
        boolean newInfo = false;
        // These rules apply iff the restrictions are on subprop and superprop
        if (this.onSubProperty(other)) {
            // scm-hv
            Set<Value> sharedValues = new HashSet<>(this.values);
            sharedValues.retainAll(other.values);
            if (!sharedValues.isEmpty()) {
                newInfo = this.addSuperClass(other) || newInfo;
            }
            else {
                // scm-svf2
                // (same result as scm-hv, no need to derive twice)
                Set<OwlClass> sharedSvf = new HashSet<>(this.svfClasses);
                sharedSvf.retainAll(other.svfClasses);
                if (!sharedSvf.isEmpty()) {
                    newInfo = this.addSuperClass(other) || newInfo;
                }
            }
            // scm-avf2
            // (applies in the other direction)
            Set<OwlClass> sharedAvf = new HashSet<>(this.avfClasses);
            sharedAvf.retainAll(other.avfClasses);
            if (!sharedAvf.isEmpty()) {
                newInfo = other.addSuperClass(this) || newInfo;
            }
        }
        return newInfo;
    }

    /**
     * Get all superclasses of the target(s) of any someValuesFrom relations
     * this class has, including the target class itself and any transitive
     * superclasses.
     */
    Set<Resource> getSvfSuperClasses() {
        Set<Resource> svfSuperClasses = new HashSet<>();
        for (OwlClass svfClass : svfClasses) {
            svfSuperClasses.addAll(svfClass.getSuperClasses());
        }
        return svfSuperClasses;
    }

    /**
     * Get all superclasses of the target(s) of any allValuesFrom relations
     * this class has, including the target class itself and any transitive
     * superclasses.
     */
    Set<Resource> getAvfSuperClasses() {
        Set<Resource> avfSuperClasses = new HashSet<>();
        for (OwlClass avfClass : avfClasses) {
            avfSuperClasses.addAll(avfClass.getSuperClasses());
        }
        return avfSuperClasses;
    }
}
