# plugIn.tcl --

# plugIn --
#   This class provides the basic interface that every plugin must comply
# with.


class plugIn {
    method init {}
    method die {}
    method documentRequest { nodeId documentInfo}
    method documentResponse { nodeId documentInfo pageList}
    method deleteNodeRequest {}
    method populateNodeRequest {}
    method _inquiryForMenu {nodeId docInfo}

}

# plugIn::init --
#    Initializes plugin. Usually here is where the plugin hooks with the 
# namespace, etc. 
# TO-DO: add arguments so we can optionally specify where we want to hook

body plugIn::init {} {}

# plugIn::die --
#    Asks the plugIn to unload itself, deleting all its nodes, etc

body plugIn::die {} {}


body plugIn::documentRequest {nodeId docInfo} {
    array set documentInfo $docInfo
    switch $documentInfo(documentType) {
        propertyPages {
	    set response [$this _inquiryForPropertyPages $nodeId $docInfo]
	    return $response
	} rightPaneContent {
	    return [$this _inquiryForRightPaneContent $nodeId $docInfo]
	 } menu {
	    return [$this _inquiryForMenu $nodeId $docInfo]
	 } wizard {
	    return [$this _inquiryForWizard $nodeId $docInfo]
	} default {
	    error "Invalid documentType $documentInfo(documentType)"
	}
    }
}


body plugIn::documentResponse { nodeId docInfo propertyPageList } {
    array set documentInfo $docInfo
    switch $documentInfo(documentType) {
        propertyPages {
	    set response [$this _receivedPropertyPages $nodeId $docInfo $propertyPageList]
	    return $response
	} wizard {
	    return [$this _receivedWizard $nodeId $docInfo $propertyPageList]
	} command {
	    return [$this _executeCommand $nodeId $docInfo]
	} default {
	    error "Invalid documentType $documentInfo(documentType)"
	}
    }
}

body plugIn::_inquiryForMenu {nodeId docInfo} {
   return [list  [list -type command -label "Add a new node" -command "" -state disabled] \
     [list -type command -label "Delete this node" -command [comanche::html::encodeURL _action deleteNodeRequest _node $nodeId]]  \
     [list -type separator] \
     [list -type command -label "Cut" -command "bla" -state disabled] \
     [list -type command -label "Copy" -command "bla" -state disabled] \
     [list -type command -label "Paste" -command "bla" -state disabled] \
     [list -type separator] \
     [list -type command -label "Configure" -command [comanche::html::createShowPropertyPagesURL $nodeId {} notag]] \
     ]
}    

namespace eval ::plugInUtils:: {
    variable addData
    variable addStructure
    variable addNode
    variable addNewNode
    variable addCaller

    set addData [xuiStructure ::#auto]
    set addStructure [xuiStructure ::#auto]
    $addStructure setName data
    
    set addCaller [xuiLabel ::#auto]
    $addCaller setName caller


    set addNewNode [xuiNode ::#auto]
    $addNewNode setName newNode
    
    set addNode [xuiNode ::#auto]
    $addNode setName node
    
    $addData addComponent $addCaller
    $addData addComponent $addStructure
    
    $addStructure addComponent $addNode
    $addStructure addComponent $addNewNode
    
    variable removeData
    variable removeStructure
    variable removeNode
    variable removeCaller

    set removeData [xuiStructure ::#auto]
    set removeStructure [xuiStructure ::#auto]
    $removeStructure setName data
    
    set removeCaller [xuiLabel ::#auto]
    $removeCaller setName caller

    set removeNode [xuiNode ::#auto]
    $removeNode setName node
    
    $removeData addComponent $addCaller
    $removeData addComponent $removeStructure
    
    $removeStructure addComponent $removeNode
    
    variable queryData
    variable queryStructure
    variable queryNode
    variable queryCaller

    set queryData [xuiStructure ::#auto]
    set queryStructure [xuiStructure ::#auto]
    $queryStructure setName data
    
    set queryCaller [xuiLabel ::#auto]
    $queryCaller setName caller
    
    set queryNode [xuiNode ::#auto]
    $queryNode setName node
    
    $queryData addComponent $addCaller
    $queryData addComponent $queryStructure
    
    $queryStructure addComponent $queryNode
}

proc ::plugInUtils::getDataField { xuiData } {

    return [$xuiData getComponentByName data]
}

proc ::plugInUtils::getCallerName { xuiData } {
    return [[$xuiData getComponentByName caller] getValue]
}

proc ::plugInUtils::getChildByClass { namespace parentNode name } {
      variable queryNode
      $queryNode setId $parentNode
      foreach child [[$namespace getChildren $queryNode null] getChildren] {
          if [$child doYouBelongTo $name] {
	      return $child
	  }
      }
}

proc ::plugInUtils::addNode { caller namespace parentNode list } {
    array set options {\
	    -openImage openFolder \
	    -closedImage closedFolder \
	    -text {default label} \
	    -classList container \
	    -container {} \
            -nodeName {} }
    array set options $list
    return [$namespace addNode $parentNode [list \
	    -text $options(-text) \
	    -openImage $options(-openImage) \
	    -closedImage $options(-closedImage) \
	    -classList $options(-classList)	    
	    ] $caller]
}


proc ::plugInUtils::removeNode { caller namespace node } {
    return [$namespace deleteNode $node $caller]
}

proc ::plugInUtils::getPageByName {selectedPageName pageList} {
    foreach page $pageList {
	if [string match [$page getName] $selectedPageName] {
	    return $page
	}
    }
    error "Not found page $selectedPageName on $pageList"
}


class nodeManagement {
    
    
    variable namespace


    variable plugIn

    variable nameMapping
    variable containerMapping
    variable childrenMapping
    variable parentMapping
    
    constructor { ns pg } {
	set namespace $ns
	set plugIn $pg
    }
    
    method addNode
    method removeNode
    method setContainer
    method getNodeName
    method getContainer
    method getChildrenByClass
    method getPlugInNodeChildren
    method getPlugInNodeChildrenByNodeName
    method getRootNode
    method getParentNode
}

body nodeManagement::setContainer { node newContainer } {
    set containerMapping($node) $newContainer
}

body nodeManagement::addNode { parentNode args } {
    array set options {\
            -openImage openFolder \
            -closedImage closedFolder \
            -text {default label} \
            -classList container \
            -container {} \
            -nodeName {} } 
    array set options $args   
    set node [::plugInUtils::addNode \
	    $plugIn $namespace $parentNode [array get options]]
    set nameMapping($node) $options(-nodeName)
    set containerMapping($node) $options(-container)
    lappend childrenMapping($parentNode) $node
    set childrenMapping($node) {}
    set parentMapping($node) $parentNode
    return $node            
}

body nodeManagement::removeNode { node } {
    foreach n $childrenMapping($node) {
        nodeManagement::removeNode $n
    } 
    ::plugInUtils::removeNode $plugIn $namespace $node
    unset nameMapping($node) 
    unset containerMapping($node)
    # lsearch and remove from list of parent node
    set parentNode $parentMapping($node) 
    lremove childrenMapping($parentNode) $node
    unset childrenMapping($node) 
    unset parentMapping($node) 
    return
}

body nodeManagement::getContainer { node } {
    return $containerMapping($node)
}

body nodeManagement::getNodeName { node } {
    return $nameMapping($node)
}

body nodeManagement::getChildrenByClass {parentNode class} {
    $queryNode setId $parentNode
    set childList [$ns getChildren $queryData] 
}

body nodeManagement::getParentNode { node } {
    return $parentMapping($node)
}

body nodeManagement::getPlugInNodeChildrenByNodeName {parentNode nodeName} {
    set result {}
    foreach child [ getPlugInNodeChildren $parentNode] {
	if { [getNodeName $child] == $nodeName } {
	    lappend result $child
	}
    }
    return $result
}

body nodeManagement::getPlugInNodeChildren {parentNode} {
    return $childrenMapping($parentNode)
}

body nodeManagement::getRootNode {} {
    return root
}


