package org.studiorailgun.ai.linguistics;

import java.util.stream.Collectors;

import org.studiorailgun.Globals;
import org.studiorailgun.ai.knowledge.Node;
import org.studiorailgun.ai.knowledge.Relation;
import org.studiorailgun.ai.knowledge.types.RelationTypes;
import org.studiorailgun.ai.philosophy.ConceptQuery;

/**
 * Collapse functions for name relations
 */
public class NameCollapse {

    /**
     * Scans a node for relations to collapse
     * @param node The node to scan
     */
    public static void collapse(Node node){
        Node nameConcept = ConceptQuery.getConcept("name");
        if(nameConcept == null){
            throw new Error("Name concept undefined!");
        }

        boolean shouldAttemptPossessionSubstitution = false;
        for(Relation childRelation : Globals.web.getRelationsOfChildNode(node)){
            switch(childRelation.getName()){
                case RelationTypes.INSTANCE_OF: {
                    /**
                     * Collapse names
                     * person(inst) <--possessionOf-- name(inst) --equals--> "John"
                     * collapses to
                     * person(inst) <-- nameOf -- "John"
                     */
                    if(childRelation.getParent().equals(nameConcept)){
                        shouldAttemptPossessionSubstitution = true;
                    }
                } break;
                default: {
                } break;
            }
        }
        // for(Relation parentRelations : Globals.web.getRelationsOfParentNode(node)){
        // }
        if(shouldAttemptPossessionSubstitution){
            NameCollapse.attemptPossessionSubstitution(node);
        }
    }

    /**
     * Attents an equivalence-to-"nameOf" substitution
     * @param node The node
     */
    private static void attemptPossessionSubstitution(Node node){
        boolean shouldAttemptPossessionSubstitution = false;
        boolean equalToName = false;
        boolean isPossession = false;
        for(Relation childRelation : Globals.web.getRelationsOfChildNode(node)){
            switch(childRelation.getName()){
                case RelationTypes.EQUALS: {
                    if(NameQuery.isName(childRelation.getParent())){
                        equalToName = true;
                    }
                } break;
                case RelationTypes.POSSESSION_OF: {
                    isPossession = true;
                } break;
                default: {
                } break;
            }
        }
        /**
         * Collapse names
         * person(inst) <--possessionOf-- name(inst) --equals--> "John"
         * collapses to
         * person(inst) <-- nameOf -- "John"
         */
        if(equalToName && isPossession){
            shouldAttemptPossessionSubstitution = true;
        }
        if(shouldAttemptPossessionSubstitution){
            Node properNoun = null;
            Node possessor = null;
            //get the proper noun
            for(Relation childRelation : Globals.web.getRelationsOfChildNode(node).stream().filter(relation -> relation.getName().equals(RelationTypes.EQUALS)).collect(Collectors.toList())){
                properNoun = childRelation.getParent();
                break;
            }
            if(properNoun == null){
                throw new Error("Failed to find the proper noun to perform the substitution with!");
            }
            //get the proper noun
            for(Relation childRelation : Globals.web.getRelationsOfChildNode(node).stream().filter(relation -> relation.getName().equals(RelationTypes.POSSESSION_OF)).collect(Collectors.toList())){
                possessor = childRelation.getParent();
                break;
            }
            if(possessor == null){
                throw new Error("Failed to find the possessor to perform the substitution with!");
            }
            NameQuery.attachName(properNoun, possessor);
        }
    }
    
}
