/*  
 *    SCCS ID: %Z%%M% %I% %E% SST
 *
 *    Copyright (c) 1992-1993 Mark Soloway.  All rights reserved.
 *    See SST_LEGAL_NOTICE file for terms of the license. 
 */  

#include <string.h>
  
#include "TreeNode_consts.h"
#include "TreeNode_server.h"
#include "TreeDisplayerChildAddedMessage.h"
#include "TreeDisplayerRefreshTreeMessage.h"
#include "TTGenericArray.h"
#include "TTC.h"

Tt_status TreeNode_server::processTreeNodeMessage (TTMessage *message)
{
  Tt_status  status;
  char      *op = message->getOp (status);

  if (!strcmp (op, TREE_NODE_OP_ADD_CHILD)) {
    status = addChild (message);
  }
  else if (!strcmp (op, TREE_NODE_OP_DELETE_NODE)) {
    status = deleteNode (message);
  }

  return status;
}

Tt_status TreeNode_server::addChild (TTMessage *message)
{
  Tt_status     status;
  TTObjectSpec *parent_object = message->getObjectSpec (status);

  if (parent_object && (status < TT_WRN_LAST)) {
    char *child_objid;

    status = message->getArgValue (0, child_objid);

    if (child_objid && (status < TT_WRN_LAST)) {
      TTObjectSpec child_object (child_objid, status);
	
      if (status < TT_WRN_LAST) {
      	status = child_object.setProperty (TREE_NODE_PARENT_PROPERTY,
					   parent_object->getID (status));
      }

      if (status < TT_WRN_LAST) {
        status = parent_object->addProperty (TREE_NODE_CHILDREN_PROPERTY,
					     child_objid);

        if (status < TT_WRN_LAST) {
	  status = parent_object->write ();

          if (status < TT_WRN_LAST) {
	    status = child_object.write ();
          }
        }
      }

      if (status < TT_WRN_LAST) {
	Tt_status temp_status;
	TTSession session (TT_INITIAL_SESSION, NULL, temp_status);

	if (temp_status == TT_OK) {
	  TreeDisplayerChildAddedMessage event (temp_status);
          (void)event.setFile (message->getFile (temp_status));
	  (void)event.setParentNode (*parent_object);
	  (void)event.setChildNode (child_object);
	  (void)session.sendAsynchronousMessage (event);
        }
      }
    }
  }

  if (parent_object)
    delete parent_object;

  return status;
}

Tt_status TreeNode_server::deleteNode (TTMessage *message)
{
  Tt_status     status;
  TTObjectSpec *node_object = message->getObjectSpec (status);

  if (!node_object || (status > TT_WRN_LAST)) {
    return status;
  }

  char *parent_objid;
  status = node_object->getProperty (TREE_NODE_PARENT_PROPERTY,
				     0,
				     parent_objid);

  if (parent_objid && (status < TT_WRN_LAST)) {
    TTGenericArray children;
    TTObjectSpec   parent_object (parent_objid, status);

    int num_children =
        parent_object.getPropertyCount (TREE_NODE_CHILDREN_PROPERTY, status);

    // Due to a bug in ToolTalk 1.0, map a TT_ERR_INTERNAL to a
    // TT_ERR_PROPNAME when getting a property count.
    if (status == TT_ERR_INTERNAL) status = TT_ERR_PROPNAME;

    if (status > TT_WRN_LAST) {
      if (status == TT_ERR_PROPNAME) status = TT_OK;
      return status;
    }

    char *peer_objid;
    for (int i=0; (status < TT_WRN_LAST) && (i < num_children); i++) {
      status = parent_object.getProperty (TREE_NODE_CHILDREN_PROPERTY,
				           i,
				           peer_objid);

      if (peer_objid && (status < TT_WRN_LAST)) {
	children.addItem ((TTGeneric *)peer_objid);
      }
    }  

    if (status < TT_WRN_LAST) {
      status = parent_object.setProperty (TREE_NODE_CHILDREN_PROPERTY,
				           (char *)NULL);
    }

    if (status < TT_WRN_LAST) {
      int num_children = children.getSize ();

      for (int i=0; (status < TT_WRN_LAST) && (i < num_children); i++) {
        if (!(*node_object == (char *)children [i])) {
          status = parent_object.addProperty (TREE_NODE_CHILDREN_PROPERTY,
					      (char *)children [i]);
        }
      }

      if (status < TT_WRN_LAST) {
	status = deleteChildren (*node_object);

        if (status < TT_WRN_LAST) { 
          status = node_object->destroy ();
        }
      }

      if (status < TT_WRN_LAST) {
	status = parent_object.write ();
      }
    }

    children.dropItems ();
  }  
  else if ((status == TT_ERR_PROPNAME) || (status < TT_WRN_LAST)) {
    status = deleteChildren (*node_object);

    if (status < TT_WRN_LAST) { 
      status = node_object->destroy ();
    }
  }

  if (status < TT_WRN_LAST) {
    Tt_status temp_status;
    TTSession session (temp_status);
 
    if (temp_status < TT_WRN_LAST) {
      TreeDisplayerRefreshTreeMessage event (temp_status);
      (void)event.setFile (message->getFile (temp_status));
      (void)session.sendAsynchronousMessage (event);
    }
  }
 
  if (node_object)
    delete node_object;

  return status;
}

Tt_status TreeNode_server::deleteChildren (const TTObjectSpec &parent)
{
  Tt_status status;

  int num_children = parent.getPropertyCount (TREE_NODE_CHILDREN_PROPERTY,
					      status);

  // Due to a bug in ToolTalk 1.0, map a TT_ERR_INTERNAL to a
  // TT_ERR_PROPNAME when getting a property count.
  if (status == TT_ERR_INTERNAL) status = TT_ERR_PROPNAME;

  if (status > TT_WRN_LAST) {
    if (status == TT_ERR_PROPNAME) {
      status = TT_OK;
    }

    return status;
  }

  char *child_objid;
  for (int i=0; (status < TT_WRN_LAST) && (i < num_children); i++) {
    status = parent.getProperty (TREE_NODE_CHILDREN_PROPERTY, i, child_objid);

    if (child_objid && (status < TT_WRN_LAST)) {
      TTObjectSpec child_object (child_objid, status);

      if (status < TT_WRN_LAST) {
        status = deleteChildren (child_object);

        if ((status == TT_ERR_OBJID) || (status < TT_WRN_LAST)) {
          status = child_object.destroy ();
	}
      }

      if (status == TT_ERR_OBJID) {
	status = TT_OK;
      }
    }
  }

  return status;
}
