/** 
 * @file    fsm.h
 * @brief   Finite State Machine
 * @author  Kenny Tran
 * @date    July 13 2022
 * @version 0.0.1
 *
 * @section LICENSES
 * Copyright (C) Morgan Advanced Programmable Systems, Inc.
 */


#ifndef FSM_H_
#define FSM_H_


/*--------------------------------------------------------------------------------------------------
 * INCLUDE FILES
 *------------------------------------------------------------------------------------------------*/
#include <stdint.h>

#include "motion.h"


/*--------------------------------------------------------------------------------------------------
 * MACROS & CONSTANTS
 *------------------------------------------------------------------------------------------------*/
#define FSM_TASK_PERIOD_MS                  (100)
#define FSM_STACK_SIZE                      (2048)
#define FSM_THREAD_PRIORITY                 (7)

#define FSM_LOW_BATTERY_BLINK_PERIOD_MS     (200)

#define FSM_CONFIG_BLINK_PERIOD_MS          (1000)
#define FSM_CONFIG_TIMEOUT_PERIOD_MS        (300000)    /* Timeout if stuck in config for 5 minutes. */

#define FSM_MOTION_TIMEOUT_PERIOD_MS        (10000)
#define FSM_MOTION_TIMEOUT_MAX_MS           (360000)    /* 6 minutes. */

#define FSM_BUTTON_PRESS_DURATION_SLEEP_MS  (3000)

#define FSM_IDLE_TIMEOUT_PERIOD_MS          (600000)    /* If idle for 10 minutes, power down. */

#define FSM_CHARGER_CONNECTED_PERIOD_MS     (400)
#define FSM_CHARGING_BLINK_PERIOD_MS        (1000)

#define FSM_FILENAME	                    ("fsm")


/*--------------------------------------------------------------------------------------------------
 * MACROS & CONSTANTS
 *------------------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------------------
 * TYPE DEFINITIONS & ENUMERATIONS
 *------------------------------------------------------------------------------------------------*/
typedef struct FSM_config
{
    uint32_t motion_timeout_ms;
    uint8_t  auto_brightness   : 8;
    uint8_t  mode              : 2;
    uint8_t  reserved_0        : 6;
    uint8_t  reserved_1        : 8;
    uint8_t  reserved_2        : 8;
} __attribute__((packed, aligned(1))) FSM_config_s;

typedef enum FSM_MODE
{
    FSM_MODE_TARGET = 0,
    FSM_MODE_3D,

    FSM_MODE_COUNT,
    FSM_MODE_INVALID = FSM_MODE_COUNT
} FSM_MODE_e;

typedef enum FSM
{
    FSM_INIT = 0,
    FSM_CHARGING,
    FSM_LOW_BATTERY,
    FSM_POWER_ON,
    FSM_IDLE,
    FSM_SLEEP,
    FSM_3D_SLEEP,
    FSM_CHARGER_CONNECTED,
    FSM_CHARGER_DISCONNECTED,
    FSM_LEVELING,
    FSM_POWER_OFF,
    FSM_OFF,
    FSM_BATTERY_FULL,
    FSM_BLE_ENABLE,
    FSM_BLE_DISABLE,

    FSM_RAINBOW,
    
    FSM_FLAT_CALIBRATE,
    FSM_BACK_CALIBRATE,
    FSM_FRONT_CALIBRATE,
    
    FSM_DEBUG = 255
} FSM_e;


/*--------------------------------------------------------------------------------------------------
 * PUBLIC FUNCTION PROTOTYPES
 *------------------------------------------------------------------------------------------------*/
void FSM_init (void);

void FSM_level_calibrate (void);

void FSM_task_suspend (void);

void FSM_task_resume (void);

void FSM_task_install (void);

void FSM_timout_set (uint32_t ms);

uint32_t FSM_timout_get (void);

void FSM_auto_brightness_set (bool enabled);

bool FSM_auto_brightness_get (void);

void FSM_mode_set (FSM_MODE_e mode);

FSM_MODE_e FSM_mode_get (void);

void FSM_app_config_set (bool val);

bool FSM_app_config_get (void);

float FSM_battery_life_get (void);

void FSM_cli_cmd (int32_t argc, char **argv);


#endif /* FSM_H_ */
