
package require unique

# namespaceServer --
#    This class implements the namespace component of the Comanche
# architecture.
#
# Inherits a namespace tree
#     It adds the following functionality
#
# Phase 1:
# - Tracks plugins<->nodes added
# - Generate events when a node is added/deleted/modified
#
# Phase 2:
# - Tracks who has browsed what and only send those events

namespace eval comanche {
}

class ::comanche::namespaceServer {
    inherit namespaceTree
 
    method documentRequest {nodeId documentInfo callerId}
    method documentResponse {nodeId documentInfo propertyPageList callerId}
    method registerConsole { console }
    method registerPlugIn { plugIn }
	
    protected method _raiseEvent { type node }
    public method addNode { node attributeList callerId}
    public method deleteNode { node callerId}
    public method deleteNodeRequest {node callerId}
    public method nodeCget { node attributeList callerId}
    
    variable _consoleList {}
    variable _plugInList {}

    # Nodes that have been added and never been requested its children
    # key: nodeId value: 0 or 1

    variable _virginNodesArray 

    # Nodes that have been browsed by a certain view
    # key: [list $node $callerId] value: 0 or 1

    variable _browsedNodesArray 

    # Which plugIn added which node
    # key: $nodeId value: $callerId

    variable _nodeOwnerArray  
}
 
 
body ::comanche::namespaceServer::documentRequest \
	{nodeId docInfo callerId} {
    array set documentInfo {documentSubtype {} skillLevel basic}
    array set documentInfo $docInfo
    switch $documentInfo(documentType) {
       rightPaneContent - propertyPages - wizard {

	   # $this here probably needs to 
	   # a) get removed: plugIns only communicate with one plugIn
	   # b) get set when registerPlugIn
	   # by now, removed $this from the end

	   set response [$_nodeOwnerArray($nodeId) documentRequest \
		   $nodeId [array get documentInfo]]
	   return $response
       } menu {
	   set response [$_nodeOwnerArray($nodeId) documentRequest \
		   $nodeId [array get documentInfo]]
	   return $response
       }
   }
}

body ::comanche::namespaceServer::documentResponse \
	{nodeId docInfo propertyPageList callerId} {
    array set documentInfo {documentSubtype {} skillLevel basic overwrite 0} 
    array set documentInfo $docInfo    
    switch $documentInfo(documentType) {
	propertyPages - wizard - command {
	    set response [$_nodeOwnerArray($nodeId) documentResponse \
		    $nodeId [array get documentInfo] $propertyPageList]
	    return $response
	}
    }
}

body ::comanche::namespaceServer::registerConsole { console } {
 
    # XXX This will be subclassed by HTTP, CORBA, etc to create the
    # actual remote object. By now, in pure Tcl, just add caller object
    #
    # In HTTP, viewer side will put $this, which will get translated
    # to appropriate remote object that then can be also created a remote
    # object in namespace and passed as $caller
   
   lappend _consoleList $console
   return $console
}

body ::comanche::namespaceServer::registerPlugIn { plugIn } {
 
    # XXX This will be subclassed by HTTP, CORBA, etc to create the
    # actual remote object. By now, in pure Tcl, just add caller object
    #
    # In HTTP, viewer side will put $this, which will get translated
    # to appropriate remote object that then can be also created a remote
    # object in namespace and passed as $caller
 
   lappend _plugInList $plugIn
   return $plugIn
}


body ::comanche::namespaceServer::_raiseEvent {type nodeId} {

    foreach console $_consoleList {
        switch $type {
	    nodeAdded {
	       set event [list \
		       -node [comanche::namespaceTree::nodeCget $nodeId {}] -change added]
	    } 
	    nodeModified {
	       set event [list \
		       -node [comanche::namespaceTree::nodeCget $nodeId {}] -change modified]
	    }
    	    nodeDeleted {
	       foreach array {_nodeOwnerArray _virginNodesArray} {
	           if [info exists ${array}($nodeId) ] {
		       unset ${array}($nodeId)
		   }
	       }
	       foreach console $_consoleList {
  		   if [info exists _browsedNodesArray([list $console $nodeId])] {
		       unset _browsedNodesArray([list $console $nodeId])
		   }
	       }
		set event [list \
			-node [list -nodeId $nodeId] -change deleted]
	    } default {
	       break
	    }
	}
	$console nodesChanged -eventList [list $event]
    }
}

body ::comanche::namespaceServer::addNode \
	{parentNode nodeAttributes callerId} {
    set nodeId [namespaceTree::addNode $parentNode $nodeAttributes]
    
    # XXX Should only do this if the above was successful

    array set _nodeOwnerArray [list $nodeId $callerId]
    return $nodeId
}

body ::comanche::namespaceServer::deleteNode \
	{nodeId callerId} {
     if ![hasChildren $nodeId] {
         namespaceTree::deleteNode $nodeId
     } else {
	 error "Cannot remove non-empty node"
     }
}

body ::comanche::namespaceServer::deleteNodeRequest \
	{nodeId callerId} {
    $_nodeOwnerArray($nodeId) deleteNodeRequest \
		   $nodeId
    return
}

body ::comanche::namespaceServer::nodeCget { node attributeList callerId} {
    set result [namespaceTree::nodeCget $node $attributeList]
    array set _browsedNodesArray [list [list $node $callerId] 1]
    return $result
}
