@name Node Graphing Chip
@inputs 
@outputs StartPos:vector EndPos:vector
@persist Nodes:table Name:string
@persist Record Editing StartPos:vector EndPos:vector Searching
@persist EndNode StartNode CurNode Links:array Eye:vector
@trigger 
runOnChat(1)

#Variables
O=owner()
K=chatClk()
Chat=O:lastSaid()
CurPos=O:pos()

#colors
White=vec(255,255,255)
Red=vec(255,0,0)
Blue=vec(0,0,255)
Green=vec(0,255,0)
Yellow=vec(255,255,0)
Black=vec()

#chat string table
Com="NGC"
Rec="rec"
Edit="edit"
Gen="gen"
On1="on"
On0="off"
Save="save"
Load="load"
Break="<"
Start="start"
End="end"
Search="search"

#Chat Checks
COM=Chat:find(Com)
REC=Chat:find(Rec)
EDIT=Chat:find(Edit)
GEN=Chat:find(Gen)
ON1=Chat:find(On1)
ON0=Chat:find(On0)
SAVE=Chat:find(Save)
LOAD=Chat:find(Load)
BRK=Chat:find(Break)
START=Chat:find(Start)
END=Chat:find(End)
SEARCH=Chat:find(Search)

#This is the if then else tree derived from the above string table and checks
if(COM&K){
    if(REC){
        if(ON1){Record=1 timer(Rec,10)}
        if(ON0){Record=0}
    }
    if(EDIT){
        if(ON1){Editing=1 timer(Edit,10)}
        if(ON0){Editing=0}
    }
    if(GEN){Generate=1 timer(Gen,10)}
    if(BRK){
        Name=Chat:explode(Break)[2,string]     
        if(SAVE){Saving=1}
        if(LOAD){Loading=1}
    }
    if(START){StartPos=O:pos()}
    if(END){EndPos=O:pos()}
    if(SEARCH){Searching=1}
}

#This creates junction points and links up any nodes that need to be
if(Generate&clk(Gen)){

}

#node recorder
if(Record&clk(Rec)){
    timer(Rec,500)
    EyeLast=Eye
    Eye=O:eye()
    if(O:vel()){  #node placement condition
        Mark=1
        MarkPos=CurPos
    }
}

#node editor
if(Editing&clk(Edit)){
    #Keep the engine running... 
    timer(Edit,20)
    
    #keys and values used for controlling the edit mode
    A1=O:keyAttack1()
    A2=O:keyAttack2()
    U=O:keyUse()
    Wep=O:weapon():type()
    Crouch=O:isCrouch()
    Ground=O:isOnGround()
    
    if(Wep:find("physcannon")&U){
        Mark=1
        MarkPos=O:aimPos()
    }

    #this is the code that finds the hologram your looking at
    findInCone(O:shootPos(),O:eye(),500,5)
    findSortByDistance(O:pos())
    Found=findResult(1)
    
    #Do something when you look at a node
    Dex=holoIndex(Found)
    if(Dex){
        holoColor(Dex,vec(0,0,255))
        Links=glonDecode(Nodes[toString(Dex),string])
        for(C=1,Links:count()){
            holoColor(Links[C,number],Red)
        }
    }


    
        
}

#Unified Node Placement Code
if(Mark){
    Size=(Nodes:count()/2)+1
    SS=toString(Size)
    Links=array()
    Links[1,number]=Size+1   #By default let's link this node to the next one
    if(Size!=1){Links[2,number]=Size-1} #and if it's not the first one let's link it to the previous one
                                        #Add more links to this array as junctions appear.
    Nodes[SS,vector]=MarkPos
    Nodes[SS,string]=glonEncode(Links) #what nodes is this one connected to?  
    holoCreate(Size,MarkPos)
}
#Node graph save function
if(Saving){

}

#Node Graph Loading function
if(Loading){

}

#find a path between two points 
if(Searching){
    # create the open list of nodes, initially containing only our starting node
    # create the closed list of nodes, initially empty

    Size=Nodes:count()/2 #because every node entry will contain a vector and string at it's index
    Open=array() Closed=array()
    ScanS=array() #Scan Start Array
    Pre=array()
    for(C=1,Size){
        CS=C:toString()
        ScanS:pushNumber(StartPos:distance(Nodes[CS,vector]))        
    }
    StartNode=ScanS:minIndex()
    
    Pre[1,number]=StartNode   #Mark start node
    Pre[2,string]=Nodes[toString(StartNode),string] #mark start node's parent as itself
    Pre[3,vector]=vec(0,0,-1) #G,H,F  Goal Cost, Hyristic, F cost
    Open:pushString(glonEncode(Pre))
    CNP=Nodes[toString(StartNode),vector] #Current Node Position
    

    while(CNP:distance(Nodes[toString(EndNode),vector])>50){  #semi arbitary distance to shut off the search function
        ScanC=array() #Scan Current Node Array
        ScanE=array() #Scan Ending Node Array
        for(C=1,Size){
            CS=C:toString()
            ScanS:pushNumber(CNP:distance(Nodes[CS,vector]))
            ScanE:pushNumber(EndPos:distance(Nodes[CS,vector]))
        }
        
        ScanC=glonDecode(Nodes[toString(StartNode),string])
        for(C=1,ScanC:count()){
            #SizeO=(Open:count()/3)+1
            #Open[toString(SizeO),number]=ScanC[C,number]
        }
        #Closed()
        EndNode=ScanE:minIndex()
        CurNode=ScanC:minIndex()
        if(StartNode==EndNode){
            break
        }else{
            #Closed[toString(CurNode),number]=1   #flags this index as "closed" 
            #Closed[toString(CurNode),string]=" " #Index of parent node
            
        }
        
    }#end while
}

#
# create the open list of nodes, initially containing only our starting node
# create the closed list of nodes, initially empty
#   while (we have not reached our goal) {
#       consider the best node in the open list (the node with the lowest f value)
#       if (this node is the goal) {
#           then we're done
#       }
#       else {
#           move the current node to the closed list and consider all of its neighbors
#           for (each neighbor) {
#               if (this neighbor is in the closed list and our current g value is lower) {
#                   update the neighbor with the new, lower, g value 
#                   change the neighbor's parent to our current node
#               }
#               else if (this neighbor is in the open list and our current g value is lower) {
#                   update the neighbor with the new, lower, g value 
#                   change the neighbor's parent to our current node
#               }
#               else this neighbor is not in either the open or closed list {
#                   add the neighbor to the open list and set its g value
#               }
#           }
#       }
#   }
