/* *********************************************************************
 * *                                                                   *
 * *             SIGMET Time Series Archive Library                    *
 * *                                                                   *
 * *********************************************************************
 * File: include/tsarchive_lib.h
 *
 *                     COPYRIGHT (c) 2003, 2005  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */
#ifndef SIGMET_TSARCHIVE_LIB_H
#define SIGMET_TSARCHIVE_LIB_H 1

/* Messages supported within the driver.
 */
#define           BAD_INDEX         1
#define TSARCHLIB_BAD_INDEX        (TSARCHLIB_FACILITY + BAD_INDEX)
#define           CLIENT_CHANGED    2
#define TSARCHLIB_CLIENT_CHANGED   (TSARCHLIB_FACILITY + CLIENT_CHANGED)
#define           CLIENT_INVALID    4
#define TSARCHLIB_CLIENT_INVALID   (TSARCHLIB_FACILITY + CLIENT_INVALID)
#define           STARTFIRST        6
#define TSARCHLIB_STARTFIRST       (TSARCHLIB_FACILITY + STARTFIRST)
#define           SETUP_CHANGED     8
#define TSARCHLIB_SETUP_CHANGED    (TSARCHLIB_FACILITY + SETUP_CHANGED)
#define           SETUP_FILE        10
#define TSARCHLIB_SETUP_FILE       (TSARCHLIB_FACILITY + SETUP_FILE)
#define           TWO_EXECUTIVE     14
#define TSARCHLIB_TWO_EXECUTIVE    (TSARCHLIB_FACILITY + TWO_EXECUTIVE)
#define           TWO_WATCHDOG      15
#define TSARCHLIB_TWO_WATCHDOG     (TSARCHLIB_FACILITY + TWO_WATCHDOG)


#ifndef MESSAGE_ONLY

/* ***************************
 * *                         *
 * *  TS Archive Structures  *
 * *    and Definitions      *
 * *                         *
 * ***************************
 */

/* Filter used to define what files are supposed to be processed */
struct tsarchlib_filter
{
  char sSiteName16[20];   /* * for don't care */
  char sTaskName[16];     /* * for don't care */
  int  iYear;             /* -1 for don't care */
  int  iMonth;            /* -1 for don't care */
  int  iDay;              /* -1 for don't care */
  int  iStartTime;        /* Time span, -1 for don't care */
  int  iEndTime;
  int  iMaxListSize;      /* Maximum number of files to list */
};

/* The number of pre canned directories available */
#define TSARCH_DIRECTORY_COUNT (8)
struct tsarchlib_setup
{
  char  sVersion[8];
  UINT1 lPlaybackRepeat;    /* repeat data when playing back */
  char  ipad9x1[1];
#define TSARCH_PB_VERSION_MAX (99)
  SINT2 iPlaybackVersion;   /* Playback version number */
  FLT4  fPlaybackSpeed;     /* Playback speed, 1=original speed */
  FLT4  fPlaybackPause;     /* Playback loop pause in seconds */
  SINT4 iInventorySize;
  char  sDirectory[DIRECTORY_SIZE];
  char  sDirectoryList[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE];

};

#define TSARCH_FILENAME_SIZE (68)  /* Should be a multiple of 4 */
struct one_ts_file
{
  SINT4 ibytes;                           /*Size in bytes*/
  UINT2 iFlags;                           /*File Status*/
#define TSARCH_OTF_DELETE    (0x0001)      /* Delete this file */
#define TSARCH_OTF_PLAYBACK  (0x0002)      /* Playback this file */
#define TSARCH_OTF_NOT_TS    (0x0004)      /* File is not TS */
#define TSARCH_OTF_LONG_NAME (0x0008)      /* Filename is to long */
#define TSARCH_OTF_TITLE     (0x0010)      /* File is title file */
#define TSARCH_OTF_ACTIVE    (0x0020)      /* File is "Active" */
  SINT2 iMaxRange;                        /* Max range in km */
  UINT2 iSweepNumber;
  char  sSiteName[17];                    /* Null term. */
  char  sTaskName[17];                    /* Null term. */
  struct ymds_time ing_time;              /* Data time */
  char  sPolarization[4];                 /* Polarization, null term */
  char sFileName[TSARCH_FILENAME_SIZE];   /*File name on disk, zero term */
};

#define TSARCH_TITLE_SIZE (64)
struct tsarchlib_dirinfo
{
  char sDirectory[DIRECTORY_SIZE];     /* Ignore if CHANGING set */

  int  iStateFlags;
#define TSARCH_DIR_MISSING    (0x001)   /* Directory is missing */
#define TSARCH_DIR_BUSY       (0x008)   /* Mount or init in progress */
#define TSARCH_DIR_ROOT_FS    (0x010)   /* Directory is on the root filesystem */
#define TSARCH_DIR_NOT_OWNER  (0x020)   /* Directory owner is not operator */
#define TSARCH_DIR_CHANGING   (0x040)   /* Directory is changing */
#define TSARCH_DIR_READ_ONLY  (0x080)   /* Directory is read only */
  int  iTotalMBytes;              /* Total space on partition in MB */
  int  iFreeMBytes;               /* Free space on partition in MB */
  int  iUsedMBytes;               /* Used space on partition in MB, calc from total&Free */
};

#define TSARCH_SITE_COUNT (8)  /* Must be a multiple of 4 */
#define TSARCH_TASK_COUNT (16)  /* Must be a multiple of 4 */
struct tsarchlib_name_list
{
  char  sName[17]; /* List of all sites found in the inventory */
};

struct tsarchlib_inventory_header
{
  UINT1 lValid;                     /* Non-zero if information is valid */
  UINT1 lPartial;                   /* Non-zero if Inventory is not complete */
  UINT1 lDelete;                    /* File is flagged for delete */
  UINT1 lNonTS;                     /* Inventory contains non-time series files */
  char sTitle[TSARCH_TITLE_SIZE];   /* Title of directory, blank if none */

  struct linear_list_header lhead;  /* List header */
  struct kilo_count num_bytes;      /* # bytes for all products */
  struct tsarchlib_name_list SiteList[TSARCH_SITE_COUNT];
  struct tsarchlib_name_list TaskList[TSARCH_TASK_COUNT];

  UINT4 iChangedBTime;              /* Time of the last change */
  UINT4 iActiveBTime;               /* Time of the last change to the active file only */
  UINT4 iDfBTime;                   /* Time of the last df command */
  SINT4 iActiveFileIndex2;          /* Index2 of the last active file, -1 if none */
};
/* Results of filter listing */
struct tsarchlib_results
{
  UINT4 lPartial;              /* List was clipped by the maximum size */
  struct kilo_count Count;     /* Number of bytes found in the list */
};


/* Semaphore related definitions */
#define TSARCH_SEMAPHORE_NUM  (4)
#define TSARCH_EF_NUM         (0)

/* Locks must be done in numerical order, lowest first */
/* Lock shared memory holding setup information */
#define TSARCH_SETUP_SEM      (LIBS_TSARCHIVE_CLUSTER + 0)
/* Lock when making significant state transitions. */
#define TSARCH_ACTION_SEM     (LIBS_TSARCHIVE_CLUSTER + 1)
/* Lock the disk inventory */
#define TSARCH_INVENTORY_SEM  (LIBS_TSARCHIVE_CLUSTER + 2)
/* Lock the message list */
#define TSARCH_MESSAGE_SEM    (LIBS_TSARCHIVE_CLUSTER + 3)

/* Most attempts to change this or to read this require locking the
 * TSARCHIVE_ACTION_SEM.  It is OK for the executive to read without
 * locking to see if the command has changed from the current mode.
 */
#define TSARCH_ACTION_STATUS_SIZE (32)
struct tsarchlib_action
{
  /* The executive will attempt to obey the command ASAP.  In the case
   * of INIT or MOUNT, it will automatically switch to STOP mode when it is finised.
   * In the case of RECORD or PLAYBACK, it will stay in that mode until
   * the user requests a different mode.
   */

  /* Some state transitions are not allowed:
   *           ------------------ New command ---------------------
   * Old Mode    Stop    Record  Playback   Init    Mount    Exit
   * ---------+--------+--------+--------+--------+--------+-------+
   * Stop     |   OK   |   OK   |   OK   |   OK   |   OK   |  OK
   * Record   |   OK   |   OK   |   OK   |   No   |   No   |  OK
   * Playback |   OK   |   OK   |   OK   |   No   |   No   |  OK
   * Init     |   OK   |   No   |   No   |   No   |   No   |  OK
   * Mount    |   OK   |   No   |   No   |   No   |   No   |  OK
   */

#define TSARCH_MODE_STOP     (0)  /* Stopped */
#define TSARCH_MODE_RECORD   (1)  /* Record data to disk */
#define TSARCH_MODE_PLAYBACK (2)  /* Playback data from disk */
#define TSARCH_MODE_INIT     (3)  /* Initialize a directory */
#define TSARCH_MODE_MOUNT    (4)  /* Mount a new directory */
#define TSARCH_MODE_EXIT     (5)  /* Time to exit */
  UINT4 iCommand;     /* Command requested by the user */
  UINT4 iMode;        /* Mode that the executive is in, set by exec only */
  char  sMountDirectory[DIRECTORY_SIZE];    /* Directory to mount/init */
  char  sInitTitle[TSARCH_TITLE_SIZE];      /* Title to init to */
  char  sStatus[TSARCH_ACTION_STATUS_SIZE]; /* Action status string */
};

/* ------------------------------
 * The information structure itself.
 */
struct tsarchlib_pinfo
{
  UINT4 iPid;
};


struct tsarchlib_state
{
  struct tsarchlib_action Action;

  UINT2 lShuttingDown ;		/* Driver attempting to shutdown */

  struct tsarchlib_pinfo Executive;
  struct tsarchlib_pinfo Watchdog;

  /* Directory state related values */
  int  iStateFlags;
  int  iTotalMBytes;                  /* Total space on partition in MB */
  int  iFreeMBytes;                   /* Free space on partition in MB */
  //  char sTitle[TSARCH_TITLE_SIZE];     /* Title of directory */

};


#define TSARCH_MESSAGE_TEXT_SIZE (80)
struct tsarchlib_message
{
  UINT4 iIndex;
  char sText[TSARCH_MESSAGE_TEXT_SIZE];
};

#define TSARCH_MESSAGE_COUNT (100)
struct tsarchlib_message_list
{
  struct tsarchlib_message  List[TSARCH_MESSAGE_COUNT];
  SINT4 iCount;
};

/* ------------------------------
 * The actual shared global antenna structure.
 */
struct tsarchlib_info
{
  /* Current information for the tsarchlib
   */
  struct tsarchlib_state State;

  /* Setup information for the tsarchlib
   */
  struct tsarchlib_setup Setup;

  /* List of errors */
  struct tsarchlib_message_list Messages;
  
} ;
/* The TS archive inventory actually consists of an array of linear list 
 * numbers followed by an array of the one_ts_file structures. 
 * The dimensions are determined from setup questions.
 */
/* 0x186a0==100000 decimal */
#define TSARCH_INVENTORY_MAX    (0x0186a0)  /* Max value for inventory depth */
#define TSARCH_INVENTORY_SEARCH (0x010000)  /* Must be GE half of max */
struct tsarchlib_inventory
{
  UINT4  isize;           /* Full size of the inventory structure  */
  UINT4  iOffsetToOtf;  /* Offset to the array of OTF structures */
  struct tsarchlib_info Info;
  struct tsarchlib_inventory_header InvHead;
  SINT4  iLList[1];
  /* struct one_ts_file file[1]; */
};

/* ********************************************
 * *                                          *
 * * Function Prototypes for Library Routines *
 * *                                          *
 * ********************************************
 */

class TsArchLib
{
 public:
  /* Get current action status for screen updates.  
   * Does not need lock.
   */
  void GetAction
    ( struct tsarchlib_action *pAction_a );

  /* Get information about the current active directory.
   * Does ot need a lock.
   */
  void GetDirectory
    ( struct tsarchlib_dirinfo *pDirectory_a );
  
  /* Insert a new error message into the list.
   */
  void InsertMessage
    ( const char *sMessage_a );

  /* UnMap the shared memory, and disconnect this process from the
   * antenna driver.  Use this when you no longer need the antenna
   * driver.  For multi-threaded programs, call this after all threads
   * are closed, for example in the exit handler.
   */
  MESSAGE Close( void );

  /* Look up a file in the inventory */
  SINT4 InventoryFileLookup
    (const struct one_ts_file *pFile_a );

  /* Set the usage numbers about the directory */
  void SetDirectoryUse
    ( void );

  /* Convert ts index1 into pointer to the file.  It will return
   * a null pointer if the index is out of the valid used range
   * of the list.  Note that index1's are not constant if the inventory
   * is not locked.  Index1's cannot be stored after unlocking
   * the inventory.  Output is cast non-volatile because of the
   * lock.
   */
  struct one_ts_file *pTsFileFromIndex1
    ( SINT4 index1_a ); /* Origin 1 index1 */

  /* Get the playback repeat flag */
  UINT1 lGetPlaybackRepeat(void);

  /* Get the playback version number. */
  SINT2 iGetPlaybackVersion(void);
  
  /* Get the playback speed (1.0 means recorded speed) */
  FLT4  fGetPlaybackSpeed(void);
  
  /* Get the playback pause in seconds */
  FLT4  fGetPlaybackPause(void);

  /* Tag a specified list of files */
#define TSARCH_TAG_DELETE    (0)  /* Delete the file */
#define TSARCH_TAG_PLAYBACK  (1)  /* Playback file */
#define TSARCH_TAG_ACTIVE    (2)  /* File is active */
#define TSARCH_TAG_INACTIVE  (3)  /* File is not active */
#define TSARCH_TAG_CLEAR     (9)  /* Erase all tags */
  void TagInventoryList
    ( struct one_ts_file List_a[],  /* List of files to tag */
      UINT4 iCommand_a,             /* Tag command to perform */
      SINT4 iCount_a );             /* Number of entries in the list */

 protected:
  TsArchLib(void);    /* Constructor */
  /* ---------------------------------------------------------------
   * ----------------- Open/Close/Powerup Routines -----------------
   * ---------------------------------------------------------------
   */
  
  /* TsArchOpen() initializes internal shared memory for subsequent
   * calls to the library.  Any additional processes needed to
   * run the ts archive are also created by this function. 
   */
  
#define TSARCH_IAM_CLIENT    (0)   /* Normal client, such as a GUI */
#define TSARCH_IAM_EXECUTIVE (1)   /* The executive process */
#define TSARCH_IAM_QUITTER   (2)   /* Quitter program */
#define TSARCH_IAM_WATCHDOG  (3)   /* The watchdog process */
  
  MESSAGE Open
    ( SINT4 iClientType_a );

  /* Set the action command.  Does not handle mount or init.
   * Locks handled internally. */
  void ActionCommandSet
    ( UINT4 iCommand_a );
  
  /* Save the current state for future powerup */
  MESSAGE SaveState( void);
  
  /* -------------------------------------------------------------
   * --------------------- Message Functions ---------------------
   * -------------------------------------------------------------
   */
  /* Get the index of the last message in the message log */
  UINT4 GetLastMessageIndex
    ( void );
  
  /* Get the specified message text.  Returns NULL if the index
   * is invalid.  Caller must free the pointer.
   */
  char *GetMessageByIndex
    ( UINT4 iIndex_a );

  struct one_ts_file *pTsFileFromIndex2
    ( SINT4 index2_a ); /* Origin 0 index2 */
  SINT4 iTsIndex2FromIndex1
    ( SINT4 index1_a ); /* Origin 1 index1 */

  
  /* Get the pointer to archive inventory file list
   */
  volatile struct one_ts_file *InventoryGetPointer(void);
    
  /* Pointer to global section for the TS Archive Lib to use. */
  volatile struct tsarchlib_inventory *pTsInventory_c ;
  volatile struct tsarchlib_info      *pTsGlobal_c ;

 private:
  MESSAGE GlobalInit
    ( const struct tsarchlib_setup *pSetup_a,
      UINT1 *lcreated_a );
  void InitFirst( void );
  MESSAGE ProcessClientType
    ( SINT4 iClientType_a, UINT1 lCreated_a );
  MESSAGE ForkRequiredProcesses( void );
  MESSAGE LoadSetup
    ( const char *sRemoteHostname_a,
      volatile struct tsarchlib_setup *pTsSetup_a );
  MESSAGE SaveSetup
    ( const char *sRemoteHostname_a,
      volatile const struct tsarchlib_setup *pTsSetup_a );

  
  UINT1 lPoweredUp_c;      /* This library is opened */
  SINT4 iTsInventorySize_c;
  SINT4 iTsInventoryId_c;

};


class TsArchClient: public TsArchLib
{
 private:
  
 public:
  MESSAGE Open(void);
  /* -------------------------------------------------------------
   * --------------------- Directory Functions -------------------
   * -------------------------------------------------------------
   */
  /* Set the active directory */
  void SetDirectory
    ( const char *sDirectory_a );
  
  /* Initialize the current active directory.  Note that the specified
   * directory is just a cross check to prevent inits when the directory
   * was just switched.  If the current active directory does not match,
   * it will not init. */
  void InitDirectory
    ( const char *sDirectory_a,
      const char *sTitle_a );   /* Set to this title */
  
  /* Get the current list of possible directories */
  void GetDirectoryList
    ( char pDirectory_a[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE] );
  
  /* Set the list of possible directories */
  void SetDirectoryList
    ( const char pDirectory_a[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE] );
  
  MESSAGE SaveState(void);

  /* Set the action command.  Does not handle mount or init.
   * Locks handled internally. */
  void ActionCommandSet
    ( UINT4 iCommand_a );

  UINT4  GetLastMessageIndex(void);
  char   *GetMessageByIndex(UINT4 iMsgIdx_a);
  /* -------------------- Inventory Functions --------------------
   */
  UINT4 GetInventoryChangedTime( void );
  UINT4 GetInventoryActiveTime( void );
  
  /* Get the inventory list.  Returns the number of entries found.
   * The list is allocated in the caller's routine, and the
   * filter specifies the maximum number of slots to use.
   */
  SINT4 GetInventoryList
    ( struct tsarchlib_inventory_header *pInvHeader_a,
      const struct tsarchlib_filter *pFilter_a,
      struct tsarchlib_results *pResults_a,
      struct one_ts_file pList_a[] );

  /* Get the active inventory file */
  SINT4 GetInventoryActiveFile
    ( UINT4 *iActiveBTime_a,
      struct one_ts_file *pFile_a );

  /* Tag all files which match the filter, tag options are the same as
   * TagInventoryList minus the ACTIVE options. */
  void TagInventoryFilter
    ( const struct tsarchlib_filter *pFilter_a,
      UINT4 iCommand_a );           /* Tag command to perform */
  /* Set the playback repeat flag */
  void SetPlaybackRepeat(UINT1 lPlaybackRepeat_a);

  /* Set the playback version number */
  void SetPlaybackVersion(SINT2 iPlaybackVersion_a);
    
  /* Set the playback speed (1.0 means recorded speed) */
  void SetPlaybackSpeed(FLT4 fPlaybackSpeed_a);
    
  /* Set the playback pause in seconds */
  void SetPlaybackPause(FLT4 fPlaybackPause_a);
  
};

class TsArchExec: public TsArchLib
{
 private:
  SINT4 InventorySiteLookup
    (const char *sSitename_a );
  SINT4 InventorySiteInsert
    (SINT4 iIndex_a,    /* Location to put the new sitename in */
     const char *sSitename_a );
  SINT4 InventoryTaskLookup
    (const char *sName_a );
  SINT4 InventoryTaskInsert
    (SINT4 iIndex_a,    /* Location to put the new sitename in */
     const char *sName_a );

 public:

  MESSAGE Open(void);
  MESSAGE Close(void);
  /* Set the action mode.  */
  void SetActionMode
    ( UINT4 iMode_a,
      const char *sStatus_a );   /* The status string */

  /* Set the action command back to STOP after a command has completed.
   * Does not require a lock. */
  void ActionCommandClear
    ( void );
  /* Set the action command to playback */
  void ActionCommandPlayback
    ( void );
  void ActionCommandMount
    ( void );

  UINT4 GetActionCommand( void );
  /* Move the new directory into effect. */
  void SwitchDirectoryName
    ( const char* sDirectory_a );   /* New directory name to use */
  /* Set the directory state. */
  void SetDirectoryState
    ( UINT4 iStateFlags_a );   /* New state flags */
  /* Set and clear directory state bits */
  void SetClrDirectoryState
    ( UINT4 iSetBits_a,
      UINT4 iClrBits_a ); 
  /* Set the inventory title */
  void SetInventoryTitle
    ( const char *sTitle_a );
  /* Set the inventory valid flag */
  void SetInventoryValid
    ( UINT1 lValid_a );
  /* Set the inventory partial flag */
  void SetInventoryPartial
    ( UINT1 lPartial_a );
  /* Set the inventory non-TS flag */
  void SetInventoryNonTs
    ( UINT1 lNonTs_a );
  /* Clear the inventory. */
  void ClearInventory(void);
  /* Add a file to the inventory */
  MESSAGE InventoryFileAdd
    (const struct one_ts_file *pFile_a,
     SINT4 *iIndex1_a );
  /* Get the current list of files tagged for playback.  Returns the 
   * number of entries found. The list is allocated in the caller's routine, 
   * and the MaxListSize the maximum number of file to return.  File are
   * in inventory order, the most recent first.
   */
  SINT4 GetInventoryPlayList
    ( SINT4  iMaxListSize_a,  /* Maximum number of files to show in the list */
      struct one_ts_file pList_a[] );

  /* Get just the header of the inventory */
  void GetInventoryHeader
    ( struct tsarchlib_inventory_header *pInvHeader_a );

  /* Add an active file to the inventory */
  MESSAGE InventoryActiveAdd
    (const struct one_ts_file *pFile_a);
  /* Update the size of the active entry. */
  void InventoryActiveUpdateSize
    (SINT4 iSize_a);
  /* Mark the active file as done. */
  void InventoryActiveDone
    (void);

  void EntryFromFileName
    ( struct one_ts_file *pFile_a,
      const char *sFile_a );

};
      
class TsArchWatch: public TsArchLib
{
 private:

 public:
  MESSAGE Open(void);

  MESSAGE Close(void) ;

  void  SetWatchdogMode( UINT4 iMode_a );

  UINT4 GetActionCommand( void );

  volatile UINT1 *GetInventoryDeletePointer( void );

  MESSAGE InventoryFileDelete
  (SINT4 index1_a,                    /* Index of product, origin 1 */
   UINT4 isem_a );
};


class TsArchQuit: public TsArchLib
{
 private:
  
 public:
  MESSAGE Open(void);
  void ActionCommandExit( void );
  /* Get the executive process PID. */
  UINT4 GetExecutivePid( void );
  /* Get the watchdog process PID */
  UINT4 GetWatchdogPid( void );
  
};

#endif /* #ifndef MESSAGE_ONLY */
#endif /* #ifndef SIGMET_TSARCHIVE_LIB_H */
