///
/// @file script.h
/// @authors k. headley
/// @date 11 aug 2017

/// script parsing

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


/////////////////////////
// Terms of use
/////////////////////////
/*
 Copyright Information
 
 Copyright 2002-2017 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 SCRIPT_H
#define SCRIPT_H

/////////////////////////
// Includes
/////////////////////////
#include <stdint.h>
#include <stdio.h>

#include "cwgsys.h"

#if defined(__PIC24FJ256GA106__) || defined(__PIC24FJ256GA606__) || defined(__PIC24FJ1024GA606__)
#include "pic24.h"
#include "ioserial.h"
#include "ff.h"
#include "ui.h"
#include "timers.h"
#endif // PIC

/////////////////////////
// Macros
/////////////////////////
#define SCR_SCRIPT_COUNT 4
#define SCR_PATH_BYTES 14
#define SCR_CONTEXT_DEPTH 1
#ifndef SCR_LINE_BUFFER_BYTES
#define SCR_LINE_BUFFER_BYTES 128
#endif 

#define ISCRLF(c) ((c=='\n'|| c=='\r') ? true : false)
#define ISCOMMENT(cp) (cp!=NULL && (*cp=='#' || (cp[0]=='/' && cp[1]=='/')) ? true : false)

#define SCR_HRANGE_VALID(hnd) ((hnd>=0 && hnd<SCR_SCRIPT_COUNT) ? true : false)
#define SCR_HND_INVALID -1
#define SCR_CTX_INVALID NULL
        
typedef struct script_ctx_s script_ctx_t;
typedef int16_t reg16_t;
typedef int32_t reg32_t;
typedef uint16_t script_flag_t;
typedef int script_hnd_t;
typedef enum{T_RUN=0,T_DELAY, SCR_TMR_COUNT}script_timer_id;
typedef enum{R16_A=0,R16_B, SCR_R16_COUNT}script_reg16_id;
typedef enum{R32_A=0, SCR_R32_COUNT}script_reg32_id;

typedef enum{
    SS_INVALID=-1,
    SS_IDLE=0,
    SS_READY,
    SS_RUN, 
    SS_DELAY,
    SS_PAUSE,
    SS_ERR
}script_state_t;

typedef enum{
    SM_AUTOLOOP=0x0001,
    SM_MAN     =0x0002,
    SM_NOSLEEP =0x0004,
    SM_DEBUG   =0x0800,
    SM_ERROR   =0x1000,
    SM_INVALID =0x8000,
    SM_ALL=0x7FFF
}script_mode_t;

typedef enum{
    SE_END=0x1,
    SE_PLAY=0x2,
    SE_PAUSE=0x4,
    SE_RESUME=0x8,
    SE_TMREXP=0x10,
    SE_FWD=0x20,
    SE_REV=0x40,
    SE_DELAY=0x80,
    SE_JMP=0x100,
    SE_ERROR=0x1000,
    SE_INVALID=0x8000,
    SE_ALL=0x7FFF
}script_event_t;

typedef enum{
    SA_NOP=0x0,
    SA_STEP=0x1,
    SA_FWD=0x2,
    SA_REV=0x4,
    SA_END=0x8,
    SA_PAUSE=0x10,
    SA_DELAY=0x20            
}script_action_t;

typedef enum{
    EOK=0,
    EEXEC,
    ECMD,
    EREAD,
    EINVAL
}script_err_t;


/////////////////////////
// Type Definitions
/////////////////////////
 struct script_ctx_s{
    char name[SCR_PATH_BYTES];
    FILE_T *fp_src;
    FILE_T file;
    Timer timer[SCR_TMR_COUNT];
    reg16_t reg16[SCR_R16_COUNT];
    script_state_t state;
    script_mode_t modes;
    script_event_t events;
    script_err_t error;
    uint32_t period;
    uint16_t line;
    return_code_t rstat;
    serial_port_t otty;
};

typedef struct script_s{
     script_ctx_t *ctx;
     script_ctx_t ctx_table[SCR_CONTEXT_DEPTH];
}script_t;

typedef return_code_t (*scr_cmd_fn)(int argc, char **argv, script_hnd_t hnd);

typedef struct ScrCmdStruct_s {
    char* name;             ///<command name(what's typed into CLI)
   scr_cmd_fn func;    ///<pointer to function to be called
}ScrCmdStruct;

#ifndef TYPEDEF_BYTE
#define TYPEDEF_BYTE
typedef uint8_t byte;
#endif

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

#ifdef __cplusplus
extern "C" {
#endif

return_code_t script_state_update();
return_code_t script_bootstrap(char *src);
return_code_t script_run_excl(char *src, bool overwrite);

return_code_t script_dispatch(char* line, const ScrCmdStruct* cmds, script_hnd_t hnd);
return_code_t script_tdispatch(int argc, char **argv, const ScrCmdStruct* cmds, script_hnd_t hnd);
return_code_t script_parse_boolex(char *expr, bool *result);
return_code_t script_parse_line(char *line, size_t len, script_hnd_t hnd);
script_hnd_t script_parse_hnd(char *arg);

script_hnd_t script_lookup(char *src);
script_hnd_t script_load(char *src, int slot, bool overwrite);
return_code_t script_unload(script_hnd_t hnd);
int32_t script_run(script_hnd_t hnd);

return_code_t script_set_period(script_hnd_t hnd, uint32_t period, bool sync);
return_code_t script_set_otty(script_hnd_t hnd, serial_port_t otty);
return_code_t script_sync(script_hnd_t hnd, uint32_t delay);
return_code_t script_reset(script_hnd_t hnd);
return_code_t script_delay(script_hnd_t hnd, uint32_t delay_ms);
return_code_t script_goto(script_hnd_t hnd, char *label);
return_code_t script_set_event(script_hnd_t hnd,script_event_t mask);
return_code_t script_set_mode(script_hnd_t hnd,script_mode_t mask);
return_code_t script_clr_mode(script_hnd_t hnd,script_mode_t mask);
script_state_t script_state(script_hnd_t hnd);

void script_show(script_hnd_t hnd, bool verbose, uint16_t indent);
char *script_name(script_hnd_t hnd);
uint32_t script_next_event();

#ifdef __cplusplus
}
#endif
#endif // THIS FILE

