///
/// @file micron.h
/// @authors k. headley
/// @date 05 dec 2019

/// Lightweight cron-like scheduler

/// @sa doxygen-examples.c for more examples of Doxygen markup


/////////////////////////
// Terms of use
/////////////////////////
/*
 Copyright Information
  
 Copyright 2002-2019 MBARI
 Monterey Bay Aquarium Research Institute, all rights reserved.
 
 Terms of Use
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version. You can access the GPLv3 license at
 http://www.gnu.org/licenses/gpl-3.0.html
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details
 (http://www.gnu.org/licenses/gpl-3.0.html)
 
 MBARI provides the documentation and software code "as is", with no warranty,
 express or implied, as to the software, title, non-infringement of third party
 rights, merchantability, or fitness for any particular purpose, the accuracy of
 the code, or the performance or results which you may obtain from its use. You
 assume the entire risk associated with use of the code, and you agree to be
 responsible for the entire cost of repair or servicing of the program with
 which you are using the code.
 
 In no event shall MBARI be liable for any damages, whether general, special,
 incidental or consequential damages, arising out of your use of the software,
 including, but not limited to, the loss or corruption of your data or damages
 of any kind resulting from use of the software, any prohibited use, or your
 inability to use the software. You agree to defend, indemnify and hold harmless
 MBARI and its officers, directors, and employees against any claim, loss,
 liability or expense, including attorneys' fees, resulting from loss of or
 damage to property or the injury to or death of any person arising out of the
 use of the software.
 
 The MBARI software is provided without obligation on the part of the
 Monterey Bay Aquarium Research Institute to assist in its use, correction,
 modification, or enhancement.
 
 MBARI assumes no responsibility or liability for any third party and/or
 commercial software required for the database or applications. Licensee agrees
 to obtain and maintain valid licenses for any additional third party software
 required.
 */

// Always do this
#ifndef MICRON_H
#define MICRON_H

/////////////////////////
// Includes 
/////////////////////////

#include <stdio.h>
#include <ctype.h>
#include "rtc.h"
#include "cwg-shared.h"
#include "schedule.h"
#include "script.h"
#include "timers.h"


/////////////////////////
// Macros
/////////////////////////
#define SYS_CRONTAB_DFL "CRONTAB.SYS"
#define USR_CRONTAB_DFL "CRONTAB.USR"
#define USR_CRONTAB_STR "USR"
#define SYS_CRONTAB_STR "SYS"

#define CRON_PATH_LEN 14
#define CRON_SCH_LEN  64
#define CRON_MAX_TASKS 4
#define CRON_TASK_IDX_VALID(i) ( (i>=0) && (i<CRON_MAX_TASKS) ? true : false)

#define CRON_HND_ISVALID(hnd) (hnd>=0 && hnd<CRON_INSTANCE_COUNT ? true : false)
// set to zero to dynamically allocate
#define CRON_LINE_BUF_BYTES 80
#define CRON_TAB_ENABLED(ptab) ( ((NULL!=ptab) && ((ptab->flags&TAB_CTRL_EN)!=0) ) ? true : false )

/////////////////////////
// Type Definitions
/////////////////////////


typedef enum{
    CRON_HND_DFL=0,
    CRON_INSTANCE_COUNT
}cron_hnd_t;

typedef enum{
    TAB_MASK_NONE=0x0000,
    TAB_MODE_EXCL=0x0001,
    TAB_CTRL_EN  =0x1000,
    TAB_MASK_ALL =0x1FFF
}tab_flags_t;

#define TAB_ENABLED(pt) ( (NULL!=pt) && (pt->flags&TAB_CTRL_EN)!=0 ? true : false)
#define TAB_EXCL(pt) ( (NULL!=pt) && (pt->flags&TAB_MODE_EXCL)!=0 ? true : false)

typedef enum{
    TABID_LIST_END=-2,
    TABID_INVALID=-1,
    TABID_SYS=0,
    TABID_USR,
    TABID_COUNT
}CRON_DFL_TAB_ID_t;

typedef enum{
    TSK_LIST_END=-2,
    TSK_INVALID=-1,
    TSK_PENDING=0,
    TSK_RUNNING,
    TSK_SUSPENDED,
}cron_task_state;

typedef int cron_tab_id;

typedef struct cron_task_s{
    cron_task_state state;
    int16_t req_n;
    schedule_t sch;
    char scr[CRON_PATH_LEN];
    script_hnd_t hnd;
    Timer run_timer;
}cron_task_t;

typedef struct cron_tab_s{
    const char *name;
    CRON_DFL_TAB_ID_t id;
    tab_flags_t flags;
    uint16_t n_tasks;
    char tab_path[CRON_PATH_LEN];
    cron_task_t *tasks;
    FILE_T *fp;
    FILE_T file;
}cron_tab_t;

typedef enum{
    CST_INVALID=-1,
    CST_READY=0,
    CST_COMPARE,
    CST_EXEC
}cron_state_t;

typedef struct cron_instance_s{
    cron_tab_t *tabs;
    uint16_t len;
    bool enabled;
    cron_state_t state;
    time_t tt_last;
    Timer suspend_timer;
}cron_instance_t;

/////////////////////////
// Exports
/////////////////////////

#ifdef __cplusplus
extern "C" {
#endif

cron_instance_t *micron_get_instance(cron_hnd_t hnd);
void micron_task_show(cron_task_t *self, int indent);
void micron_tab_show(cron_tab_t *self, int indent);
void micron_show(cron_instance_t *self, int indent);
cron_tab_t *micron_tab_slookup(cron_hnd_t hnd, char *key);
cron_tab_t *micron_tab_ilookup(cron_hnd_t hnd, cron_tab_id id);
int micron_tab_init(cron_tab_t *self, char *tab_path);
int micron_tab_list(cron_hnd_t hnd, cron_tab_id id);
int micron_tab_stat(cron_hnd_t hnd, cron_tab_id id,int indent);
int micron_tab_set_path(cron_tab_t *self, char *path, bool keep_flags);
int micron_tab_set_task(cron_tab_t *self, int idx, schedule_t sch, char *scr);
int micron_tab_reset_task(cron_tab_t *self, int idx);
int micron_tab_suspend_task(cron_tab_t *self, int idx,bool suspend);
cron_task_t *micron_tab_get_task(cron_tab_t *self, int idx);
char *micron_tab_get_script(cron_tab_t *self, int idx);
byte *micron_tab_get_schedule(cron_tab_t *self, int idx);
int micron_tab_set_flags(cron_tab_t *self, tab_flags_t flags);
int micron_tab_clr_flags(cron_tab_t *self, tab_flags_t flags);
int micron_tab_parse_flags(cron_tab_t *self, char *flag_str);
int micron_parse_cron(char **psch, char **pscr, char *src, char *del);
int micron_set_enable(cron_hnd_t hnd, bool enable);
bool micron_get_enable(cron_hnd_t hnd);
int micron_suspend(cron_hnd_t hnd, uint32_t period_msec);
bool micron_suspended(cron_hnd_t hnd, uint32_t *r_stimer);
int micron_resume(cron_hnd_t hnd);
void micron_task_init(cron_task_t *self);
int micron_task_parse(cron_task_t *dest, char *src);
int micron_task_update(cron_task_t *self, Time *ptm, tab_flags_t flags);
uint32_t micron_task_reset_timer(cron_task_t *self);
int micron_tab_update(cron_tab_t *self, Time *ptm);
int micron_update_tabs(cron_hnd_t hnd, Time *ptm);
int micron_init(cron_instance_t *self);
int micron_state_update(cron_hnd_t hnd);
char *micron_qtrim_str(char *src);
uint32_t micron_next_event(cron_hnd_t hnd, Time *tm);

#ifdef __cplusplus
}
#endif

#endif // THIS_FILE
