package org.studiorailgun.ai.knowledge.anchor;

import java.util.Map;

import org.studiorailgun.Globals;
import org.studiorailgun.ai.knowledge.Node;

/**
 * Anchor nodes for the rest of the web
 */
public class AnchorNodes {
    
    /**
     * The node that represents the self
     */
    Integer self;

    /**
     * The node that represents the idea of a concept
     */
    Integer concept;

    /**
     * The concept of a quality
     */
    Integer quality;

    /**
     * The concept of a name
     */
    Integer name;

    /**
     * Used for flagging a node at learnable
     */
    Integer learnable;

    /**
     * Gets the self
     * @return The self node
     */
    public Node getSelfNode() {
        if(self == null){
            return null;
        }
        return Globals.web.getNode(self);
    }

    /**
     * Sets the self node ID
     * @param id The self node's ID
     */
    public void setSelf(int id) {
        this.self = id;
    }

    /**
     * Gets the id for the self node
     * @return The id
     */
    public Integer getSelf(){
        return self;
    }

    /**
     * Gets the idea of a concept
     * @return The idea of a concept
     */
    public Node getConceptNode() {
        if(concept == null){
            return null;
        }
        return Globals.web.getNode(concept);
    }

    /**
     * Sets the concept node
     * @param id The concept node
     */
    public void setConcept(int id){
        this.concept = id;
    }

    /**
     * Gets the id for the concept node
     * @return The id for the concept node
     */
    public Integer getConcept(){
        return concept;
    }

    /**
     * Gets the idea of a quality
     * @return The idea of a quality
     */
    public Node getQualityNode() {
        if(quality == null){
            return null;
        }
        return Globals.web.getNode(quality);
    }

    /**
     * Sets the quality node
     * @param id The quality node
     */
    public void setQuality(int id){
        this.quality = id;
    }

    /**
     * Gets the id for the quality node
     * @return The id for the quality node
     */
    public Integer getQuality(){
        return quality;
    }

    /**
     * Gets the idea of a name
     * @return The idea of a name
     */
    public Node getNameNode() {
        if(name == null){
            return null;
        }
        return Globals.web.getNode(name);
    }

    /**
     * Sets the name node
     * @param id The name node
     */
    public void setName(int id){
        this.name = id;
    }

    /**
     * Gets the id for the name node
     * @return The id for the name node
     */
    public Integer getName(){
        return name;
    }

    /**
     * Gets the idea of a learnable
     * @return The idea of a learnable
     */
    public Node getLearnableNode() {
        if(learnable == null){
            return null;
        }
        return Globals.web.getNode(learnable);
    }

    /**
     * Sets the learnable node
     * @param id The learnable node
     */
    public void setLearnable(int id){
        this.learnable = id;
    }

    /**
     * Gets the id for the learnable node
     * @return The id for the learnable node
     */
    public Integer getLearnable(){
        return learnable;
    }

    /**
     * Copies anchor nodes from the child to the parent
     * @param parentAnchors The parent anchors
     * @param childAnchors The child anchors
     */
    public static void copyToParent(AnchorNodes parentAnchors, AnchorNodes childAnchors){
        if(childAnchors.getConcept() != null){
            parentAnchors.setConcept(childAnchors.getConcept());
        }
        if(childAnchors.getSelf() != null){
            parentAnchors.setSelf(childAnchors.getSelf());
        }
        if(childAnchors.getQuality() != null){
            parentAnchors.setQuality(childAnchors.getQuality());
        }
        if(childAnchors.getName() != null){
            parentAnchors.setName(childAnchors.getName());
        }
        if(childAnchors.getLearnable() != null){
            parentAnchors.setLearnable(childAnchors.getLearnable());
        }
    }

    /**
     * Updates the IDs for the anchor nodes based on the newly assigned IDs after loading
     * @param crossRelationLookupMap The crossrelational lookup map
     * @param tag The tag for the current web
     */
    public void updateReferences(Map<String,Integer> crossRelationLookupMap, String tag){
        int oldId;
        String lookupId = null;
        int newNodeId;
        try {
            if(this.getSelf() != null){
                oldId = this.getSelf();
                lookupId = "node-" + tag + oldId;
                newNodeId = crossRelationLookupMap.get(lookupId);
                this.setSelf(newNodeId);
            }
            if(this.getConcept() != null){
                oldId = this.getConcept();
                lookupId = "node-" + tag + oldId;
                newNodeId = crossRelationLookupMap.get(lookupId);
                this.setConcept(newNodeId);
            }
            if(this.getQuality() != null){
                oldId = this.getQuality();
                lookupId = "node-" + tag + oldId;
                newNodeId = crossRelationLookupMap.get(lookupId);
                this.setQuality(newNodeId);
            }
            if(this.getName() != null){
                oldId = this.getName();
                lookupId = "node-" + tag + oldId;
                newNodeId = crossRelationLookupMap.get(lookupId);
                this.setName(newNodeId);
            }
            if(this.getLearnable() != null){
                oldId = this.getLearnable();
                lookupId = "node-" + tag + oldId;
                newNodeId = crossRelationLookupMap.get(lookupId);
                this.setLearnable(newNodeId);
            }
        } catch (NullPointerException ex){
            throw new Error("Failed to find node link " + lookupId + " in relation in web " + tag);
        }
    }

    /**
     * Checks for errors in the anchor definitions
     */
    public void errorCheck(){
        if(self == null){
            throw new Error("self undefined!");
        }
        if(concept == null){
            throw new Error("concept undefined!");
        }
    }

}
