// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*-

/// @brief	Imposes limits on location (geofence), altitude and other parameters.
///         Each breach will trigger an action or set of actions to recover. Adapted from geofence.
/// @author Andrew Tridgell
///         Andreas Antonopoulos

#ifndef AP_LIMITS_H
#define AP_LIMITS_H

#ifndef AP_LIMITS
 #define AP_LIMITS ENABLED
#endif

#include <stdint.h>
#include <AP_Limit_Module.h>
#include <AP_Common.h>

// MAVLink messages, trying to pull into library
//#include "../GCS_MAVLink/include/mavlink/v1.0/protocol.h"
//#include "../GCS_MAVLink/include/mavlink/v1.0/mavlink_types.h"
//#include "../GCS_MAVLink/include/mavlink/v1.0/common/mavlink.h"
//#include "../GCS_MAVLink/include/mavlink/v1.0/ardupilotmega/mavlink_msg_limits_status.h"



#ifndef HAVE_ENUM_LIMITS_STATE
 #define HAVE_ENUM_LIMITS_STATE
enum LimitState {
    LIMITS_INIT,                        // pre-initialization
    LIMITS_DISABLED,                    // disabled
    LIMITS_ENABLED,                     // checking limits
    LIMITS_TRIGGERED,                   // a limit has been breached
    LIMITS_RECOVERING,                  // taking action, eg. RTL
    LIMITS_RECOVERED,                   // we're no longer in breach of a limit
};
#endif

class AP_Limits {

public:

    AP_Limits();

    // access functions
    bool        enabled();
    bool        debug();
    bool        required();
    AP_Int8        state();
    AP_Int8        safetime();
    AP_Int8        channel();
    AP_Int8        recmode();

    // module linked list management methods
    void                    modules(AP_Limit_Module *m);             // pointer to the first module in linked list of modules
    AP_Limit_Module *       modules_first();
    AP_Limit_Module *       modules_current();
    AP_Limit_Module *       modules_last();
    AP_Limit_Module *       modules_next();
    void                    modules_add(AP_Limit_Module *m);
    uint8_t                 modules_count();

    // main limit methods
    bool                    init();                                     // initialize self and all modules
    void                    set_state(int s);             // change state
    bool                    check_all();                        // check if any limit is triggered
    bool                    check_required();                   // check if any of the required modules is triggered
    bool                    check_triggered(bool required);             // the function that does the checking for the two above

    uint32_t                last_trigger;             // time of last limit breach (trigger)
    uint32_t                last_action;             // time of last recovery action taken
    uint32_t                last_recovery;             // time of last recovery success
    uint32_t                last_status_update;             // time of last recovery success
    uint32_t                last_clear;             // last time all triggers were clear (or 0 if never clear)

    uint16_t                breach_count;             // count of total breaches

    byte                    old_mode_switch;

    LimitModuleBits         mods_enabled;
    LimitModuleBits         mods_required;
    LimitModuleBits         mods_triggered;
    LimitModuleBits         mods_recovering;


    static const struct AP_Param::GroupInfo        var_info[]; // module parameters

protected:
    AP_Int8                 _enabled;             // the entire AP_Limits system on/off switch
    AP_Int8                 _required;             // master switch for pre-arm checks of limits. Will not allow vehicle to "arm" if breaching limits.
    AP_Int8                 _debug;              // enable debug console messages
    AP_Int8                 _safetime;             // how long after recovered before switching to stabilize
    AP_Int8                 _state;             // overall state - used in the main loop state machine inside the vehicle's slow loop.
    AP_Int8                 _channel;             // channel used for switching limits on/off
    AP_Int8                 _recmode;             // recovery mode: 0=RTL mode, 1=bounce mode

private:
    AP_Limit_Module *       _modules_head;      // points to linked list of modules
    AP_Limit_Module *       _modules_current;      // points to linked list of modules
    uint8_t                 _modules_count;

};


#endif // AP_LIMITS_H
