package org.studiorailgun.knowledge.query;

import java.util.List;
import java.util.stream.Collectors;

import org.studiorailgun.Globals;
import org.studiorailgun.knowledge.Node;
import org.studiorailgun.knowledge.Relation;
import org.studiorailgun.knowledge.query.filter.NameQueryFilter;
import org.studiorailgun.knowledge.types.RelationTypes;

/**
 * Queries for dealing with instances of nodes
 */
public class InstanceQuery {
    
    /**
     * Gets the instances of a node
     * @param web The web
     * @param parent The parent node
     * @return The list of instances of that node
     */
    public static List<Node> getInstances(Node parent){
        List<Relation> relations = Globals.web.getRelationsOfParentNode(parent);
        return relations.stream().filter(relation -> relation.getName().equals(RelationTypes.INSTANCE_OF)).map(relation -> relation.getChild()).collect(Collectors.toList());
    }

    /**
     * Gets a concept by its name
     * @param web The web
     * @param conceptName The name of the concept
     * @return The concept
     */
    public static Node getConcept(String conceptName){
        Node concept = Globals.web.getAnchors().getConceptNode();
        List<Node> concepts = InstanceQuery.getInstances(concept);
        return NameQueryFilter.withNodeName(concepts, conceptName);
    }

    /**
     * Gets the most specific concept that the child is an instance of
     * @param child The child
     * @return The most specific concept that the child is an instance of
     */
    public static Node getMostSpecificConcept(Node child){
        //get all concepts
        Node concept = Globals.web.getAnchors().getConceptNode();
        List<Node> concepts = InstanceQuery.getInstances(concept);

        //get the objects the child is an instance of
        List<Relation> relations = Globals.web.getRelationsOfChildNode(child);


        //filter to most specific concept
        List<Node> conceptParents = relations.stream()
            .filter(relation -> relation.getName().equals(RelationTypes.INSTANCE_OF))
            .filter(relation -> concepts.contains(relation.getParent()))
            .map(relation -> relation.getParent()).collect(Collectors.toList());

        if(conceptParents.size() < 1){
            throw new Error("Node somehow has no concept that it is an instance of! " + concept.getName());
        }

        //TODO: get most specific -- defaulting to first currently
        return conceptParents.get(0);
    }

}
