#include "core/config.h"
#if CONFIG_AUTOMAT_MODE || CONFIG_LEDS
#ifndef ROUTINE_SEQUENCE_H
#define ROUTINE_SEQUENCE_H
#include <stdint.h>
#include <stdbool.h>

#define RSA_STRICT_CHECKS                      0    

#define RSA_USE_LOCKERS                        1

typedef bool fRoutine_t( void * arg );
//------------------------------------------------------------------------------
typedef struct
{
    int32_t           idx;              // pending routine index
    uint32_t          count;            // amount of routines in list
    uint32_t          size;             // size of routine list
    fRoutine_t **     papfRoutineList;  // routine list
    void *            arg;              // user argument to be passed
    
    #if RSA_USE_LOCKERS > 0
    fRoutine_t *      fLocker;
    fRoutine_t *      fUnlocker;
    #endif
}
sRoutineSequence_t; //=Routine Sequence Entry
//------------------------------------------------------------------------------
// rsa_sequence_init()
// Initialize sRoutineSequence_t before any operations
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be initialized
// * IN [ void * ] @arg - an user argument to be passed into each routine
// * IN [ fRoutine_t ** ] @papfRoutineList - the routine list to hold the values
// * IN [ uint32_t ] @size - the size of routine list array @papfRoutineList
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_init( sRoutineSequence_t * pSeq, void * arg, fRoutine_t ** papfRoutineList, uint32_t size );
//------------------------------------------------------------------------------
#if RSA_USE_LOCKERS > 0
// rsa_sequence_setlockers()
// Specifies a special Lock/Unlock function to be used during all procedures
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be initialized
// * IN [ fRoutine_t * ] @fLocker - a function to be used to lock the object @pSeq
// * IN [ fRoutine_t * ] @fUnlocker - a function to be used to unlock the object @pSeq
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_setlockers( sRoutineSequence_t * pSeq, fRoutine_t * fLocker, fRoutine_t * fUnlocker );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_insert_routine()
// Inserts a routine into the routine sequence
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// * IN [ fRoutine_t * ] @routine - a routine to be inserted
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_insert_routine( sRoutineSequence_t * pSeq, fRoutine_t * routine );
#if RSA_USE_LOCKERS > 0
bool rsa_sequence_iinsert_routine( sRoutineSequence_t * pSeq, fRoutine_t * routine );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_remove_routine()
// Removes the lastest routine from the routine sequence
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_remove_routine( sRoutineSequence_t * pSeq );
#if RSA_USE_LOCKERS > 0
bool rsa_sequence_iremove_routine( sRoutineSequence_t * pSeq );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_call()
// Implements an ordinar call of the routines sequence
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], end of sequence sign, true = sequence completed, false = sequence is in progress
bool rsa_sequence_call( sRoutineSequence_t * pSeq );
#if RSA_USE_LOCKERS > 0
bool rsa_sequence_icall( sRoutineSequence_t * pSeq );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_reset()
// Resets the routines sequence and makes it to be restarted
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_reset( sRoutineSequence_t * pSeq );
#if RSA_USE_LOCKERS > 0
bool rsa_sequence_ireset( sRoutineSequence_t * pSeq );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_clear()
// Clears all the routines in the sequence
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], result of operation, true = success, false = error
bool rsa_sequence_clear( sRoutineSequence_t * pSeq );
#if RSA_USE_LOCKERS > 0
bool rsa_sequence_iclear( sRoutineSequence_t * pSeq );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_skip_routine()
// Skips the current routine into the routine sequence
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], result of operation, true = success, false = error
#if RSA_USE_LOCKERS > 0 
bool rsa_sequence_skip_routine( sRoutineSequence_t * pSeq );
bool rsa_sequence_iskip_routine( sRoutineSequence_t * pSeq );
#else
bool rsa_sequence_iskip_routine( sRoutineSequence_t * pSeq );
#endif
// -----------------------------------------------------------------------------
// rsa_sequence_back_routine()
// Rolls the routine sequence back and make the previous routine to be called
// Params: 
// * IN/OUT [ sRoutineSequence_t ] @pSeq - the sequence to be modified
// Returns:
// [ bool ], result of operation, true = success, false = error
#if RSA_USE_LOCKERS > 0 
bool rsa_sequence_back_routine( sRoutineSequence_t * pSeq );
bool rsa_sequence_iback_routine( sRoutineSequence_t * pSeq );
#else
bool rsa_sequence_iback_routine( sRoutineSequence_t * pSeq );
#endif
#endif
#endif