/*  File:         broker.c
 *  Created:      20-10-95
 *  Updated:      30-12-95
 *  Version:      1.0
 *  Project:      Clicker
 *  Owner:        Jeroen Vermeulen
 *  Requirements: KickStart V39+
 *  Legal:        PD
 *  Status:       Release
 */

#include <proto/exec.h>
#include <exec/memory.h>
#include <proto/commodities.h>
#include <proto/alib.h>

#include "main.h"
#include "broker.h"

static STRPTR
        InstallFailCxBrk = "Couldn't set up commodities broker!\n",
        AllocFailCxObj   = "Unable to create CX object!\n";


/* MakeBroker():
 * Creates and initializes a NewBroker structure, including its MsgPort.
 * Call KillBroker() to get rid of it later. If allocation fails for
 * some reason, NULL is returned and the pointer indicated by errptr is
 * redirected to an error string.
 */
struct NewBroker *MakeBroker(STRPTR *const errptr, const BYTE cx_pri)
{
  struct NewBroker *mybroker=NULL;
  struct MsgPort   *msgport;

  /* --- */

  if ((msgport = CreateMsgPort()))
  {
    mybroker = AllocMem(sizeof(struct NewBroker),MEMF_PUBLIC|MEMF_ANY);
    if (mybroker)
    {
      mybroker->nb_Version = NB_VERSION;
      mybroker->nb_Name = "Clicker";
      mybroker->nb_Title = descrp;
      mybroker->nb_Descr = "Keyclick";
      mybroker->nb_Unique = NBU_UNIQUE | NBU_NOTIFY;
      mybroker->nb_Flags = COF_SHOW_HIDE;
      mybroker->nb_Pri = cx_pri;
      mybroker->nb_Port = msgport;
      mybroker->nb_ReservedChannel = 0;
    }
    else
    {
      *errptr = InstallFailCxBrk;
      DeleteMsgPort(msgport);
    }
  }
  else *errptr = AllocFailMsgPort;
  return(mybroker);
}


/* KillBroker():
 * Delete a NewBroker structure (and its MsgPort) that was allocated
 * through MakeBroker(). Calling this for an unitialized or NULL broker
 * is safe, as long as initialization was done by MakeBroker().
 */
void KillBroker(struct NewBroker *const brokerobj)
{
  if (brokerobj)
  {
    struct MsgPort *port;
    /* --- */
    if ((port = brokerobj->nb_Port))
    {
      struct Message *msg;
      /* --- */
      while ((msg = GetMsg(port))) ReplyMsg(msg);
      DeleteMsgPort(port);
    }
    FreeMem(brokerobj,sizeof(struct NewBroker));
  }
}


/* SetupBroker():
 * Sets up the commodities broker network for Clicker (created with
 * MakeBroker()) in an inactive state.  Activate or deactivate it with
 * ActivateCxObj().
 * If successful, a pointer to the root CxObj is returned, so it can later be
 * deallocated with DeleteCxObjAll().  If an error occurs, NULL is returned and
 * the STRPTR pointed to by errptr will point to an error message.
 */
CxObj *SetupBroker(STRPTR *const errptr, struct NewBroker *const mybroker)
{
  CxObj  *brokerobj;
  LONG    cxreturn=CBERR_OK;

  /* --- */

  brokerobj = CxBroker(mybroker,&cxreturn);

  switch (cxreturn)
  {
    case CBERR_OK:
      {
        CxObj *const senderobj = CxSender(mybroker->nb_Port,0);
        BOOL   okay = FALSE;
        /* --- */
        if (senderobj)
        {
          AttachCxObj(brokerobj,senderobj);
          if (!(okay = !CxObjError(senderobj))) *errptr = AllocFailCxObj;
        }
        else *errptr = AllocFailCxObj;

        if (!okay)
        {
          DeleteCxObjAll(brokerobj);
          brokerobj = NULL;
        }
      }
    break;

    case CBERR_DUP:
    break;

    default:
      *errptr = InstallFailCxBrk;
    break;
  }

  return brokerobj;
}
