#ifndef MTS_IO_ICELLULARRADIO_H
#define MTS_IO_ICELLULARRADIO_H

#include <string>
#include <vector>
#include <functional>

#include <json/json.h>

#include <mts/MTS_AutoPtr.h>
#include <mts/MTS_IO_SerialConnection.h>

#define EXPORT __attribute__((visibility("default")))

namespace MTS {
    namespace IO {
        class EXPORT ICellularRadio
        {
            public:
                typedef std::function<bool(const std::string&/*iterationData*/, const std::string&/*allData*/)> IsNeedMoreData;
                typedef std::function<void(const Json::Value&)> UpdateCb;

                //Registration Values
                enum REGISTRATION : uint8_t {
                    NOT_REGISTERED = 0,
                    REGISTERED = 1,
                    SEARCHING=2,
                    DENIED=3,
                    UNKNOWN=4,
                    ROAMING=5
                };

                enum SERVICEDOMAIN : uint8_t {
                    NO_SERVICE = 0,
                    CS_ONLY = 1,
                    PS_ONLY = 2,
                    CSPS = 3
                };

                enum ACTIVEBAND : uint8_t {
                    GSM_850 = 0,
                    GSM_900 = 1,
                    DCS_1800 = 2,
                    PCS_1900 = 3
                };

                enum CODE : uint8_t {
                    SUCCESS = 0,
                    ERROR,
                    FAILURE,
                    NO_RESPONSE,
                    NOT_APPLICABLE,
                    INVALID_ARGS
                };

                enum SIMSTATUS : uint8_t {
                    READY = 0,
                    LOCKED,
                    BLOCKED,
                    NOT_INSERTED
                };

                enum CELLULAR_MODES : uint8_t {
                    CELLULAR_MODE_NA = 0, // NOT AVAILABLE
                    CELLULAR_MODE_2G = 1 << 0, // GSM
                    CELLULAR_MODE_3G = 1 << 1, // WCDMA
                    CELLULAR_MODE_4G = 1 << 2, // LTE
                    CELLULAR_MODE_5G = 1 << 3  // 5G
                };

                enum UE_MODES_OF_OPERATION : uint8_t {
                    UNKNOWN_MODE = 0, // current mode of operation is not available
                    PS_MODE1, // only EPS (LTE) services are allowed, the usage is "voice centric"
                    PS_MODE2, // only EPS (LTE) services are allowed, the usage is "data centric"
                    CS_PS_MODE1, // both EPS and non-EPS services are allowed, the usage is "voice centric"
                    CS_PS_MODE2, // both EPS and non-EPS services are allowed, the usage is "data centric"
                    CS_MODE1, // only non-EPS services are allowed, the usage is "voice centric"
                    CS_MODE2 // only non-EPS services are allowed, the usage is "data centric"
                };

                static CODE convertModelToType(const std::string& sModel, std::string& sType);
                static CODE convertModelToMtsShortCode(const std::string& sModel, std::string& sCode, ICellularRadio *radioObj = NULL);
                static CODE convertServiceDomainToString(SERVICEDOMAIN eSd, std::string& sSd);
                static CODE convertActiveBandToString(ACTIVEBAND eBand, std::string& sBand);
                static CODE convertUeModeToString(ICellularRadio::UE_MODES_OF_OPERATION mode, std::string& sMode);
                static CODE convertStringToUeMode(const std::string& sMode, ICellularRadio::UE_MODES_OF_OPERATION& mode);

                static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo,
                                               const std::string& sCmd,
                                               IsNeedMoreData& isNeedMoreData,
                                               int32_t timeoutMillis = 100,
                                               const char& ESC = CR);
                static std::string sendCommand(MTS::AutoPtr<MTS::IO::Connection>& apIo,
                                               const std::string& sCmd,
                                               const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
                                               int32_t timeoutMillis = 100,
                                               const char& ESC = CR);

                //! Wait for response from the radio without sending any data to it
                static std::string waitResponse(MTS::AutoPtr<MTS::IO::Connection>& apIo,
                                                IsNeedMoreData& isNeedMoreData,
                                                int32_t timeoutMillis = 100);
                static std::string waitResponse(MTS::AutoPtr<MTS::IO::Connection>& apIo,
                                                const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
                                                int32_t timeoutMillis = 100);

                static CODE test(MTS::AutoPtr<MTS::IO::Connection>& apIo, uint32_t timeoutSeconds = 30);
                static std::string extractModelFromResult(const std::string& sResult);
                static std::string getCodeAsString(CODE code);

                static const char *DEFAULT_RADIO_PORT;
                static const char *DEFAULT_RADIO_DIR;

                static const char *VALUE_UNKNOWN;
                static const char *VALUE_UNAVAILABLE;
                static const char *VALUE_NOT_SUPPORTED;

                //Special Payload Characters
                static const char ETX;  //Ends socket connection
                static const char DLE;  //Escapes ETX and DLE within Payload
                static const char CR;
                static const char NL;
                static const char CTRL_Z;

                static const char *RSP_OK;
                static const char *RSP_ERROR;
                static const char *RSP_CONNECT;

                static const char *VALUE_NOT_REGISTERED;
                static const char *VALUE_REGISTERED;
                static const char *VALUE_SEARCHING;
                static const char *VALUE_DENIED;
                static const char *VALUE_ROAMING;

                //Static Data
                static const char *KEY_TYPE;          //!< GSM or CDMA
                static const char *KEY_CODE;          //!< Product Code : H5, H6, C2, EV3, G3
                static const char *KEY_MODEL;         //!< Model : HE910, CE910, DE910, GE910
                static const char *KEY_MANUFACTURER;  //!< Manufacturer: Telit
                static const char *KEY_HARDWARE;      //!< Radio Hardware Version
                static const char *KEY_FIRMWARE;      //!< Radio Firmware Version
                static const char *KEY_FIRMWARE_BUILD;//!< Radio Firmware Build
                static const char *KEY_VENDOR_FIRMWARE;  //!< Radio Vendor Firmware Version
                static const char *KEY_IMEI;          //!< International Mobile Station Equipment Identity
                static const char *KEY_MEID;          //!< Mobile Equipment Identifier
                static const char *KEY_IMSI;          //!< International Mobile Subscriber Identity
                static const char *KEY_MSID;          //!< Mobil Station ID (MSID) aka MIN aka MSIN aka Last few digits of IMSI
                static const char *KEY_MDN;           //!< Mobile Directory Number : Actual phone number dialed to reach radio
                static const char *KEY_CARRIER;       //!< Cellular Service Provider (Home Network)
                static const char *KEY_ICCID;         //!< Integrated Circuit Card Identifier
                static const char *KEY_MSL;           //!< Master Subsidy Lock
                static const char *KEY_SUPPORTED_CELL_MODES;  //!< Comma-separated list of all supported cellular modes (2g,3g,4g)
                static const char *KEY_SIM_CARRIER_CODE;  //!< Unique carrier identifier based on the SIM card information.


                //Network Status Data
                static const char *KEY_ROAMING;       //!< Indicates whether or not using Home Network
                static const char *KEY_DATETIME;      //!< Date and Time from tower
                static const char *KEY_SERVICE;       //!< Service Connection Type [GPRS, EGPRS, WCDMA, HSDPA, 1xRTT, EVDO]
                static const char *KEY_CELL_MODE;     //!< Specifies the cellular mode that is currently used by the modem [2g, 3g, 4g]
                static const char *KEY_NETWORK;       //!< Cellular Service Provider
                static const char *KEY_NETWORK_REG;   //!< Network Registration
                static const char *KEY_CID;           //!< Cellular ID (Tower) in HEX
                static const char *KEY_LAC;           //!< Location Area Code in HEX
                static const char *KEY_RAC;           //!< Routing Area Code in HEX
                static const char *KEY_RSSI;          //!< Received Signal Strength Indication
                static const char *KEY_RSSIDBM;       //!< Received Signal Strength Indication in dBm
                static const char *KEY_MCC;           //!< Mobile Country Code
                static const char *KEY_MNC;           //!< Mobile Network (Operator) Code
                static const char *KEY_CHANNEL;       //!< ARFCN or UARFCN Assigned Radio Channel
                static const char *KEY_TXPWR;         //!< Transmit Power
                static const char *KEY_PSC;           //!< Active Primary Synchronization Code (PSC)
                static const char *KEY_ECIO;          //!< Active Ec/Io (chip energy per total wideband power in dBm)
                static const char *KEY_RSCP;          //!< Active RSCP (Received Signal Code Power in dBm)
                static const char *KEY_DRX;           //!< Discontinuous reception cycle length (ms)
                static const char *KEY_MM;            //!< Mobility Management State
                static const char *KEY_RR;            //!< Radio Resource State
                static const char *KEY_NOM;           //!< Network Operator Mode
                static const char *KEY_ABND;          //!< Active Band
                static const char *KEY_BLER;          //!< Block Error Rate (percentage)
                static const char *KEY_SD;            //!< Service Domain
                static const char *KEY_DEBUG;         //!< Debug Information

                static const char *KEY_MIP;                //!< Mobile IP Information
                static const char *KEY_MIP_ID;             //!< MIP Profile ID
                static const char *KEY_MIP_ENABLED;         //!< MIP Profile Enabled/Disabled
                static const char *KEY_MIP_NAI;            //!< Network Access Identifier
                static const char *KEY_MIP_HOMEADDRESS;    //!< Home Address
                static const char *KEY_MIP_PRIMARYHA;      //!< Primary Home Agent
                static const char *KEY_MIP_SECONDARYHA;    //!< Secondary Home Agent
                static const char *KEY_MIP_MNAAASPI;       //!< Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index
                static const char *KEY_MIP_MNHASPI;        //!< Mobile Node Home Agent Security Server Parameter Index
                static const char *KEY_MIP_REVTUN;         //!< Reverse Tunneling Enabled
                static const char *KEY_MIP_MNAAASS;        //!< Mobile Node Authentication, Authorization, and Accounting Server Shared Secret
                static const char *KEY_MIP_MNHASS;         //!< Mobile Node Home Agent Shared Secret

                //SIM Status Summary data
                static const char *KEY_IS_SIM_INSERTED;    //!< SIM card insertion indicator. True when a SIM card is inserted
                static const char *KEY_IS_SIM_LOCKED;      //!< SIM card lock status indicator. True when a SIM card is locked by PIN / PUK / other code
                static const char *KEY_SIM_LOCK_STATUS;    //!< SIM card lock status string. Either "READY", "SIM PIN", "SIM PUK" or other state
                static const char *KEY_ATTEMPTS_PIN;       //!< The number of attempts left to unlock the SIM card using PIN code
                static const char *KEY_ATTEMPTS_PUK;       //!< The number of attempts left to unlock the SIM card using PUK code

                //Values - Type
                static const char *VALUE_TYPE_LTE;
                static const char *VALUE_TYPE_GSM;
                static const char *VALUE_TYPE_CDMA;

                //Values - Carrier
                static const char *VALUE_CARRIER_VERIZON;
                static const char *VALUE_CARRIER_AERIS;
                static const char *VALUE_CARRIER_SPRINT;
                static const char *VALUE_CARRIER_USCELLULAR;
                static const char *VALUE_CARRIER_ATT;
                static const char *VALUE_CARRIER_TMOBILE;

                static const char *VALUE_SD_NO_SERVICE;
                static const char *VALUE_SD_CS_ONLY;
                static const char *VALUE_SD_PS_ONLY;
                static const char *VALUE_SD_CSPS;

                static const char *VALUE_ABND_GSM_850;
                static const char *VALUE_ABND_GSM_900;
                static const char *VALUE_ABND_DCS_1800;
                static const char *VALUE_ABND_PCS_1900;

                //Values - Carrier code; abstraction over PLMN IDs, IINs and other identifiers
                static const char *VALUE_CARRIER_CODE_VERIZON;
                static const char *VALUE_CARRIER_CODE_ATT;

                static const std::vector<std::string> DEFAULT_BAIL_STRINGS;

                virtual ~ICellularRadio() = 0;

                virtual bool initialize(uint32_t iTimeoutMillis = 5000) = 0;
                virtual bool resetRadio(uint32_t iTimeoutMillis = 5000) = 0;
                virtual bool resetConnection(uint32_t iTimeoutMillis = 5000) = 0;
                virtual void shutdown() = 0;

                virtual const std::string& getName() const = 0;

                virtual CODE getModel(std::string& sModel) = 0;

                virtual CODE getFirmware(std::string& sFirmware) = 0;
                virtual CODE getFirmwareBuild(std::string& sFirmwareBuild) = 0;
                virtual CODE getVendorFirmware(std::string& sVendorFirmware) = 0;
                virtual CODE getHardware(std::string& sHardware) = 0;
                virtual CODE getManufacturer(std::string& sManufacturer) = 0;
                virtual CODE getImei(std::string& sImei) = 0;
                virtual CODE getMeid(std::string& sMeid) = 0;
                virtual CODE getImsi(std::string& sImsi) = 0;
                virtual CODE getSimStatus(std::string& sSimStatus) = 0;

                virtual CODE getSupportedCellularModes(CELLULAR_MODES &networks) = 0;
                virtual CODE getCellularMode(CELLULAR_MODES &networks) = 0;
                virtual CODE setCellularMode(CELLULAR_MODES networks) = 0;

                /**
                 * @brief getSimStatusSummary - get summary on the SIM card status
                 *        (if there is a SIM card inserted, is it locked, etc).
                 *        See below for the full list of returned fields.
                 *
                 * - `isSimInserted` - bool, is the SIM card installed or not;
                 * - `isSimLocked` - bool, is the SIM card blocked with PIN/PUK or not (or is READY);
                 * - `lockStatus` - string, either "READY", "SIM PUK", "SIM PIN" or other status as
                 *    returned by "AT+CPIN?" AT command;
                 * - `attemptsPin` - integer, the number of attempts lef to enter a PIN code;
                 * - `attemptsPuk` - integer, the number of attempts lef to enter a PUK code.
                 *
                 * **Only `isSimInserted` is always present.** All other fields are omitted if
                 * the SIM card is removed.
                 *
                 * @param jData - an object to be filled with data
                 * @return CODE::SUCCESS on success,
                 *         CODE::NOT_APPLICABLE if not supported by this radio
                 *         and CODE::ERROR otherwise
                 */
                virtual CODE getSimStatusSummary(Json::Value& jData) = 0;

                virtual CODE getIccid(std::string& sIccid) = 0;
                virtual CODE getService(std::string& sService) = 0;
                virtual CODE getLac(std::string& sLac) = 0;
                virtual CODE getMdn(std::string& sMdn) = 0;
                virtual CODE getMsid(std::string& sMsid) = 0;
                virtual CODE getType(std::string& sType) = 0;
                virtual CODE getCarrier(std::string& sCarrier) = 0;
                virtual CODE getNetwork(std::string& sNetwork) = 0;
                virtual CODE getTower(std::string& sTower) = 0;
                virtual CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) = 0;
                virtual CODE getRoaming(bool& bRoaming) = 0;

                virtual CODE getSignalStrength(int32_t& iRssi) = 0;
                virtual CODE getModemLocation(std::string& sLocation) = 0;
                virtual CODE convertSignalStrengthTodBm(const int32_t& iRssi, int32_t& dBm) = 0;
                virtual CODE convertdBmToSignalStrength(const int32_t& dBm, int32_t& iRssi) = 0;

                virtual CODE getRegistration(REGISTRATION& eRegistration) = 0;
                virtual CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) = 0;

                virtual CODE convertCellModesToString(CELLULAR_MODES eCellModes, std::string& sCellModes) = 0;

                /**
                 * @brief unlockSimCard - unlock the SIM card using PIN code provided
                 *
                 * This command does not peform any checks on the number of attempts left.
                 * Use with caution, verify the SIM status manually before execution.
                 *
                 * @param jArgs - a JSON object with the following format:
                 *
                 *        jArgs = {
                 *            "pin" : "A correct PIN code to unlock the SIM card: STRING"
                 *        }
                 *
                 * @return CODE::SUCCESS when SIM card was succeffully unlocked,
                 *         CODE::INVALID_ARGS when passed arguments are invalid,
                 *         CODE::ERROR otherwise (i.e. when modem is not responding,
                 *         when SIM card is removed, when PIN code is not correct
                 *         or on any other error).
                 */
                virtual CODE unlockSimCard(const Json::Value& jArgs) = 0;

                /**
                 * @brief getSimCarrierCode - get unique carrier identifier based on
                 *        the SIM card information.
                 *
                 * @param sCarrier - a string to be populated with one of the carrier codes:
                 *
                 *        - VALUE_CARRIER_CODE_VERIZON - Verizon
                 *        - VALUE_CARRIER_CODE_ATT - AT&T
                 *        - VALUE_UNKNOWN - Unknown carrier
                 *        - other values may be defined in the future
                 *
                 * @return CODE::SUCCESS when carrier code retrieved,
                 *         CODE::ERROR otherwise (i.e. when modem is not responding,
                 *         when SIM card is removed or on any other error).
                 */
                virtual CODE getSimCarrierCode(std::string& sCarrierCode) = 0;

                //! Gather details of the radio's Mobile IP Profile
                /*!
                 \param Json::Value object that will be populated with MIP data
                 \return Returns result code of gathering MIP
                 */
                virtual CODE getMipProfile(Json::Value& jMipProfile) = 0;

                /*
                 * jArgs = {
                 *     "msl" : "Master Subsidy Lock (Aeris, Sprint): STRING"
                 * }
                 */
                virtual CODE validateMsl(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "mdn" : "Mobile Directory Number : STRING",
                 *     "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING"
                 * }
                 */
                virtual CODE setMdn(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "msid" : "Mobil Station ID (MSID) aka MIN aka MSIN : STRING",
                 *     "msl" : "[OPTIONAL] Master Subsidy Lock (Aeris, Sprint): STRING"
                 * }
                 */
                virtual CODE setMsid(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "activeProfile" : "Set active profile: STRING"
                 * }
                 */
                virtual CODE setMipActiveProfile(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "nai" : "Network Access Identifier : STRING"
                 * }
                 */
                virtual CODE setMipNai(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "homeIp" : "Home Address : STRING"
                 * }
                 */
                virtual CODE setMipHomeIp(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "primaryHa" : "Primary Home Agent : STRING"
                 * }
                 */
                virtual CODE setMipPrimaryHa(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "secondaryHa" : "Secondary Home Agent : STRING"
                 * }
                 */
                virtual CODE setMipSecondaryHa(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "mnAaaSpi" : "Mobile Node Authentication, Authorization, and Accounting Server Security Parameter Index : STRING"
                 * }
                 */
                virtual CODE setMipMnAaaSpi(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "mnHaSpi" : "Mobile Node Home Agent Security Server Parameter Index : STRING"
                 * }
                 */
                virtual CODE setMipMnHaSpi(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "revTun" : "[DESCRIPTION] : STRING"
                 * }
                 */
                virtual CODE setMipRevTun(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "mnAaaSs" : "Mobile Node Authentication, Authorization, and Accounting Server Shared Secret : STRING"
                 * }
                 */
                virtual CODE setMipMnAaaSs(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = {
                 *     "mnHaSs" : "Mobile Node Home Agent Shared Secret : STRING"
                 * }
                 */
                virtual CODE setMipMnHaSs(const Json::Value& jArgs) = 0;

                /*
                 * jArgs = null
                 */
                virtual CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb) = 0;

                /*
                 * jArgs = null
                 */
                virtual CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) = 0;

                /*
                 * jArgs = null
                 */
                virtual CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) = 0;

                /**
                 * @brief updateFumoLocal - Performs the radio firmware upgrade using local firmware image.
                 *
                 * This command uploads (injects) the whole delta firmware image to the radio, performs the
                 * upgrade and waits for it to complete.
                 *
                 * @param fd - file descriptor of a file that shall be injected to the radio.
                 * @param stepCb - callback to receive status updates during the firmware upgrade.
                 * @return CODE::SUCCESS when the firmware upgrade was successful,
                 *         CODE::INVALID_ARGS when the file can't be opened for reading,
                 *         CODE::FAILURE when upgrade failed on the radio side,
                 *         CODE::NOT_APPLICABLE when not supported by this radio,
                 *         CODE::ERROR otherwise.
                 */
                virtual CODE updateFumoLocal(int fd, UpdateCb& stepCb) = 0;

                /**
                 * @brief fumoLocalInject - upload delta file to the radio's internal memory.
                 *
                 * This command uploads (injects) the whole delta firmware image to some place that
                 * can be later used by the radio to perform the Delta Radio Firmware Upgrade.
                 *
                 * This delta firmware image is NOT validated on the firmware image upload step.
                 *
                 * @param fd - file sescriptor of a file that shall be uploaded to the radio.
                 * @param stepCb - callback to receive status updates during the upload.
                 * @return CODE::SUCCESS when the file was successfully uploaded,
                 *         CODE::INVALID_ARGS when the file can't be opened for reading,
                 *         CODE::NOT_APPLICABLE when not supported by this radio,
                 *         CODE::ERROR otherwise.
                 */
                virtual CODE fumoLocalInject(int fd, UpdateCb& stepCb) = 0;

                /**
                 * @brief fumoLocalApply - apply the delta file that was previously uploaded.
                 *
                 * This commands initializes and tracks the progress of the delta firmware upgrade
                 * procedure using the delta firmware image file that was previously uploaded
                 * into internal memory of the radio.
                 *
                 * See ICellularRadio::fumoLocalInject to upload the file and prepare
                 * for the upgrade.
                 *
                 * @param fd - file descriptor of a file that shall be uploaded to the radio.
                 * @param stepCb - the callback to receive status updates during the upgrade.
                 * @return CODE::SUCCESS when the firmware upgrade was successful,
                 *         CODE::FAILURE when upgrade failed on the radio side,
                 *         CODE::NOT_APPLICABLE when not supported by this radio,
                 *         CODE::ERROR otherwise.
                 */
                virtual CODE fumoLocalApply(UpdateCb& stepCb) = 0;

                /**
                 * @brief fumoLocalCleanup - remove the delta file from the radio's internal memory.
                 *
                 * This command allows to remove the old delta firmware image from the radio's internal
                 * memory for cases when it's no longer needed.
                 *
                 * @return CODE::SUCCESS when the file was successfully deleted,
                 *         CODE::FAILURE when the file can't be deleted (i.e. no such file),
                 *         CODE::NOT_APPLICABLE when not supported by this radio,
                 *         CODE::ERROR otherwise.
                 */
                virtual CODE fumoLocalCleanup() = 0;

                /*
                 * jArgs = {
                 *     "msl" : "Master Subsidy Lock (Sprint): STRING"
                 * }
                 */
                virtual CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) = 0;

                /*
                 * jArgs = {
                 *     "mdn" : "Mobile Directory Number (Aeris): STRING"
                 *     "msid" : "Mobile Station ID (Aeris): STRING"
                 * }
                 */
                virtual CODE activate(const Json::Value& jArgs, UpdateCb& stepCb) = 0;

                /*
                 * jArgs = {
                 *     "enabled" : "RX Diversity Enabled ("0" or "1"): STRING"
                 * }
                 */
                virtual CODE setRxDiversity(const Json::Value& jArgs) = 0;
                /*
                 * jArgs = {
                 *     "fwid" : "Firmware Image To Be Enabled: STRING"
                 * }
                 */

                virtual CODE startOmaDm(UpdateCb& stepCb) = 0;

                virtual CODE setActiveFirmware(const Json::Value& jArgs) = 0;
                virtual CODE getActiveFirmware(std::string& sFwId) = 0;

                virtual CODE getEcho(bool& bEnabled) = 0;
                virtual CODE setEcho(bool bEnabled = true) = 0;

                virtual CODE getStaticInformation(Json::Value& jData) = 0;
                virtual CODE getNetworkStatus(Json::Value& jData) = 0;

                virtual CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = CR) = 0;

                virtual std::string sendCommand(const std::string& sCmd,
                                                const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
                                                int32_t timeoutMillis = 100,
                                                const char& ESC = CR) = 0;

                virtual std::string sendCommand(const std::string& sCmd,
                                                IsNeedMoreData& isNeedMoreData,
                                                int32_t timeoutMillis = 100,
                                                const char& ESC = CR) = 0;

                //! Wait for response from the radio without sending any data to it
                virtual std::string waitResponse(const std::vector<std::string>& vBail = DEFAULT_BAIL_STRINGS,
                                                 int32_t timeoutMillis = 100) = 0;

                //! Wait for response from the radio without sending any data to it
                virtual std::string waitResponse(IsNeedMoreData& isNeedMoreData,
                                                 int32_t timeoutMillis = 100) = 0;

                virtual CODE setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) = 0;
                virtual CODE getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) = 0;
        };
    }
}

#endif