#ifndef __MARVELMIND_API_H_
#define __MARVELMIND_API_H_

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#define MM_USB_DEVICE_ADDRESS 255

#define MM_MAX_DEVICES_COUNT 255

bool mmAPIVersion(uint32_t *version);

bool mmGetLastError(uint32_t *error);

bool mmOpenPort();
bool mmOpenPortByName(char *portName);
void mmClosePort();

typedef struct {
     uint8_t fwVerMajor;
     uint8_t fwVerMinor;
     uint8_t fwVerMinor2;
     uint8_t fwVerDeviceType;

     uint8_t fwOptions;

     uint32_t cpuId;
} MarvelmindDeviceVersion;
bool mmGetVersionAndId(uint8_t address, MarvelmindDeviceVersion *mmDevVersion);

typedef struct {
     uint8_t address;
     bool isDuplicatedAddress;
     bool isSleeping;

     uint8_t fwVerMajor;
     uint8_t fwVerMinor;
     uint8_t fwVerMinor2;
     uint8_t fwVerDeviceType;

     uint8_t fwOptions;

     uint8_t flags;
} MarvelmindDeviceInfo;
typedef struct {
    uint8_t numDevices;
    MarvelmindDeviceInfo devices[MM_MAX_DEVICES_COUNT];
} MarvelmindDevicesList;
bool mmGetDevicesList(MarvelmindDevicesList *mmDevices);

#define MM_LOCATIONS_VERSION 2

#define MM_LOCATIONS_PACK_SIZE 6
#define MM_USER_PAYLOAD_BUF_SIZE 128
typedef struct {
      uint8_t address;
      uint8_t headIndex;
      int32_t x_mm;
      int32_t y_mm;
      int32_t z_mm;
      uint8_t statusFlags;
      uint8_t quality;
      uint8_t reserved[2];
} MarvelmindDeviceLocation;
typedef struct {
      MarvelmindDeviceLocation pos[MM_LOCATIONS_PACK_SIZE];

      bool lastDistUpdated;
      uint8_t reserved[5];

      uint8_t userPayloadSize;
      uint8_t userPayloadBuf[MM_USER_PAYLOAD_BUF_SIZE];
} MarvelmindLocationsPack;
bool mmGetLastLocations(MarvelmindLocationsPack *posPack);

typedef struct {
      uint8_t address;
      uint8_t headIndex;
      int32_t x_mm;
      int32_t y_mm;
      int32_t z_mm;
      uint8_t statusFlags;
      uint8_t quality;
      uint8_t reserved[2];
      uint16_t angle;
      bool angleReady;
} MarvelmindDeviceLocation2;
typedef struct {
      MarvelmindDeviceLocation2 pos[MM_LOCATIONS_PACK_SIZE];

      bool lastDistUpdated;
      uint8_t reserved[5];

      uint8_t userPayloadSize;
      uint8_t userPayloadBuf[MM_USER_PAYLOAD_BUF_SIZE];
} MarvelmindLocationsPack2;
bool mmGetLastLocations2(MarvelmindLocationsPack2 *posPack);

typedef struct {
     uint8_t moveType;
     uint8_t reserved[8];
} MarvelmindMoveSettings;
bool mmRobotMove(uint8_t address, MarvelmindMoveSettings *moveCtrl);

bool mmRobotStop(uint8_t address);

typedef struct {
    int16_t voltage_mv;
    int16_t current_ma;
    int16_t power_left;
    int16_t power_right;
    int16_t odo_speed_left;
    int16_t odo_speed_right;

    uint8_t reserved[64];
} MarvelmindBoxieTelemetry;
bool mmGetBoxieTelemetry(uint8_t address, MarvelmindBoxieTelemetry *boxieTel);

#define BOXIE_LIDARS_NUM 12
typedef struct {
    uint16_t range_mm;
    uint8_t status;
    uint8_t reserved;
} MarvelmindBoxieLidar;
typedef struct {
    MarvelmindBoxieLidar lidars[BOXIE_LIDARS_NUM];

    uint8_t reserved[64];
} MarvelmindBoxieLidars;
bool mmGetBoxieLidars(uint8_t address, MarvelmindBoxieLidars *boxieLidars);

typedef struct {
    int32_t x_mm;
    int32_t y_mm;
    int32_t z_mm;

    int16_t angle_yaw;

    uint8_t reserved[64];
} MarvelmindBoxieLocation;
bool mmGetBoxieLocation(uint8_t address, MarvelmindBoxieLocation *boxiePos);

typedef struct {
     uint8_t itemIndex;
     uint8_t totalItemsNum;

     uint8_t opCode;
     int16_t param1;
     int16_t param2;
     int16_t param3;
} MarvelmindRobotProgramItem;
bool mmSetRobotProgramItem(uint8_t address, MarvelmindRobotProgramItem *progItem);

typedef struct {
     uint8_t commandId;

     int16_t param1;
     int16_t param2;
     int16_t param3;
} MarvelmindRobotCommand;
bool mmSetRobotCommand(uint8_t address, MarvelmindRobotCommand *robotCommand);

bool mmDeviceIsModem(uint8_t deviceType);
bool mmDeviceIsBeacon(uint8_t deviceType);
bool mmDeviceIsHedgehog(uint8_t deviceType);
bool mmDeviceIsRobot(uint8_t deviceType);

void marvelmindAPILoad();
void marvelmindAPIFree();

#ifdef __cplusplus
}
#endif

#endif // __MARVELMIND_API_H_
