
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

#include <clib/AMarquee_protos.h>

#include <pragmas/AMarquee_pragmas.h>

#define UNLESS(x) if (!(x))

struct Library * AMarqueeBase = NULL;
struct QSession * session     = NULL;

void CleanExit(void)
{
  if (session)      QFreeSession(session);       /* This MUST be done before we close the library! */
  if (AMarqueeBase) CloseLibrary(AMarqueeBase);
  printf("All done.\n");
}

/* Main program--simply increments our counter whenever someone else increments theirs */
int main(int argc, char ** argv)
{
  char * connectTo, * progName;
  int port = 2957;
  int count = 0, syncOp;
  
  atexit(CleanExit);
    
  printf("SyncTest:  This program continually updates an integer on the server.\n");
  printf("           It uses QGOF_SYNC synchronization so that any other clients\n");
  printf("           who subscribe to this entry (named \"count\") should never\n");
  printf("           miss an update.\n");
  if (argc < 2) 
  {
    printf("Usage:  SyncTest hostname [myname]\n");
    exit(RETURN_WARN);
  }
  connectTo = argv[1] ? argv[1] : "localhost";
  progName  = argv[2] ? argv[2] : "synctest";

  if ((AMarqueeBase = OpenLibrary("amarquee.library",37L)) == NULL)
  {
    printf("Couldn't open amarquee.library v37!\n");
    exit(RETURN_ERROR);
  }
  printf("Connecting to %s:%i...\n",connectTo, port);
  if ((session = QNewSession(connectTo, port, progName)) == NULL)
  {
    printf("Couldn't connect to server %s:%i\n",connectTo, port);
    CloseLibrary(AMarqueeBase);
    exit(RETURN_WARN);
  }
  printf("SyncTest connected to server %s:%i\n",connectTo, port);

  /* Setup */
  UNLESS(QSetOp(session, "count", &count, sizeof(count))) 
  {
    printf("Couldn't do QSetOp(), aborting!\n");
    Signal(FindTask(NULL), SIGBREAKF_CTRL_C);
  }
  syncOp = QGo(session,QGOF_SYNC);  /* Start it off! */

  while(1)
  {
    struct QMessage * qMsg;
    ULONG signals = (1L << session->qMsgPort->mp_SigBit) | (SIGBREAKF_CTRL_C);

    /* Wait for next message from the server */
    signals = Wait(signals);
    
    if (signals & (1L << session->qMsgPort->mp_SigBit))
    {
      while(qMsg = (struct QMessage *) GetMsg(session->qMsgPort))
      {
        if (qMsg->qm_Status != QERROR_NO_ERROR) 
        {
          printf("Error %i detected! Aborting\n", qMsg->qm_Status);
          Signal(FindTask(NULL), SIGBREAKF_CTRL_C);
        }
        else
        {
          if (qMsg->qm_ID == syncOp)
          {
            /* It's the sync signal, meaning everyone else has seen our update */
            count++;

            printf("Synced, now uploading %li... ",count); fflush(stdout);

            UNLESS((QSetOp(session, "count", &count, sizeof(count)))&&
                   (syncOp = QGo(session, QGOF_SYNC)))
            {
              printf("Upload failed, aborting\n");
              Signal(FindTask(NULL), SIGBREAKF_CTRL_C);
            }
            printf("Now awaiting sync signal (id %i).\n",syncOp);
          }
        }
        FreeQMessage(session,qMsg);
      }
    }
    if (signals & SIGBREAKF_CTRL_C) break;  /* Quit if CTRL-C pressed */
  }
  
  /* CleanExit called here via the atexit() feature */
}
