/*
 * exec: A plugin for the Video Disk Recorder
 * Copyright (C) 2007  Winfried Koehler
 * Licence GPL
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#ifndef __EXEC_EXECTIMER_H_
#define __EXEC_EXECTIMER_H_

#include <vdr/plugin.h>
#include <vdr/tools.h>

/* exec timer flags */
#define ET_NONE         0x00000000ULL /* unspecified, default   */
#define ET_DEFAULT      0x00000102ULL /* bash, background       */
#define ET_FOREGROUND   0x00000001ULL /* used for shell command */
#define ET_BACKGROUND   0x00000002ULL /* used for shell command */
#define ET_WAKEUP       0x00000004ULL /* wake up vdr if needed  */
//                      0x00000008ULL /* RESERVED               */
//                      0x00000010ULL /* RESERVED               */
//                      0x00000020ULL /* RESERVED               */
//                      0x00000040ULL /* RESERVED               */
//                      0x00000080ULL /* RESERVED               */
#define ET_MASK_SHFLAG  0x000000FFULL /* mask shell flags       */

#define ET_SHELLCOMMAND 0x00000100ULL /* shell command          */
#define ET_SHUTDOWN     0x00000200ULL /* shutdown command vdr   */
#define ET_MESSAGE      0x00000400ULL /* Skins.Message          */
#define ET_WARNING      0x00000800ULL /* Skins.Warning          */
//                      0x00001000ULL /* RESERVED               */
//                      0x00002000ULL /* RESERVED               */
//                      0x00004000ULL /* RESERVED               */
//                      0x00008000ULL /* RESERVED               */
#define ET_MASK_ACT     0x0000FF00ULL /* mask to find action    */

#define ET_IGNORE_DATE  0x00010000ULL /* ignore date            */
#define ET_IGNORE_TIME  0x00020000ULL /* ignore time            */
//                      0x00040000ULL /* RESERVED               */
//                      0x00080000ULL /* RESERVED               */
#define ET_MASK_DAYTIME 0x000F0000ULL /* mask to find date/time */

/* weekdays */
#define WD_IGNORED      0x00000000ULL /* single shot timer      */
#define WD_MONDAY       0x00000001ULL
#define WD_TUESDAY      0x00000002ULL
#define WD_WEDNESDAY    0x00000004ULL
#define WD_THURSDAY     0x00000008ULL
#define WD_FRIDAY       0x00000010ULL
#define WD_SATURDAY     0x00000020ULL
#define WD_SUNDAY       0x00000040ULL
#define WD_DAILY        0x0000007FULL /* sum of all days above  */
//                      0x00000080ULL /* RESERVED               */
#define WD_MASK         0x000000FFULL

#define EXEC_LOG        100

/****************************************************************************** 
 * some helper funcs here
 *****************************************************************************/

time_t Now(void);

/****************************************************************************** 
 * cTaskThread
 *****************************************************************************/

class cTaskThread : public cThread {
private:
  bool active;
  int * state;
  int * logstate;
  cCondWait cw;
protected:
  virtual void Action(void);
public:
  cTaskThread(int * State, int * LogState);
  void Stop(void) {active=false; cw.Signal();}; 
  virtual ~cTaskThread(void);
};

/****************************************************************************** 
 * class cExecTimer
 *****************************************************************************/

class cExecTimer : public cListObject {
private:
  time_t startTime;
  int    timeout;
  int    Day;
  int    Time;
  char * command;
  char * wd_str;
  bool   active;
  bool   running;
  bool   started;
  long long flags;
  long long weekdays;
public:
  cExecTimer(time_t StartTime=Now(),
    const char * Command="(NULL)", int TimeOut=-1);
  virtual ~cExecTimer();
  bool    isActive   (){ return active;   }; /* returns wether timer is enabled             */
  bool    isRunning  (){ return running;  }; /* returns wether command is actually executed */
  bool    wasStarted (){ return started;  }; /* returns wether command was actually started */
  long long Flags    (){ return flags;   };
  void      SetFlags (long long f)
                       { flags = f;      };
  long long WeekDays (){ return weekdays;};
  void    SetActive  (bool a)
                       { active = a;     };
  void    SetWeekDays(long long w)
                       { weekdays = w;   };
  int     GetDay     (){ return Day;     };
  int     GetTime    (){ return Time;    };
  void    SetTime    (time_t t, int offset); 
  time_t  StartTime  ();                  /* get next start time for today               */
  bool    Expired    ();                  /* repeated timers will never expire           */
  bool    Parse      (const char * s);    /* be careful here!                            */
  bool    Save       (FILE *f);           /*                                             */
  cString ToSVDRDescr() const;            /* be careful here!                            */
  cString PrintWeekdays () const;
  cString PrintDay   () const;
  cString PrintTime  (bool colon = false) const;
  cString Command    () const;
  void    SetCommand (const char *cmd)
                       { asprintf(&command,"%s",cmd); };
  bool    Execute    ();
};

/****************************************************************************** 
 * class cExecTimers
 *****************************************************************************/

class cExecTimers : public cConfig<cExecTimer> {
private:
  int state;
  int beingEdited;
  time_t lastTimerStart;
  time_t lastDeleteExpired;
public:
  cExecTimers(void);

    /* Returns true if any of the exectimers have 
       been modified, which is detected by State 
       being different than the internal state.
       Upon return the internal state will be stored
       in State. see VDR/include/timers.h         */    
  bool Modified      (int &State);
  void SetModified   (void) { state++;                          };
  void SetTimerStart (void) { lastTimerStart=Now();             };
  int  BeingEdited   (void) { return beingEdited;               };
  void IncBeingEdited(void) { beingEdited++;                    };
  void DecBeingEdited(void) { if (beingEdited>0) beingEdited--; };
  void DeleteExpired (void);               
  void CheckTimers   (void);              /* time to execute something?                  */
  cExecTimer *GetNextActiveTimer(void);   /* get the next timer (for today !!)           */
  cExecTimer *GetNextWakeupTimer(void);   /* get the next timer for wakeup               */
  };

extern cExecTimers ExecTimers;

/****************************************************************************** 
 * class cExecLogLine
 *****************************************************************************/

class cExecLogLine : public cListObject {
private:
  char * str;
public:
  cExecLogLine(const char * Str="(NULL)");
  virtual ~cExecLogLine();
  bool    Parse      (const char * s);    /* be careful here!                            */
  bool    Save       (FILE *f);           /*                                             */
  cString Text       () const;
};

/****************************************************************************** 
 * class cExecLog
 *****************************************************************************/

class cExecLog : public cConfig<cExecLogLine> {
private:
  int state;
  int beingEdited;
public:
  cExecLog(void); 
  bool Modified      (int &State);
  void SetModified   (void) { state++;                          };
  int  BeingEdited   (void) { return beingEdited;               };
  void IncBeingEdited(void) { beingEdited++;                    };
  void DecBeingEdited(void) { if (beingEdited>0) beingEdited--; };
  void AddToLog      (const char * s, ...);
  };

extern cExecLog ExecLog;




#endif
