#pragma once

#include "nlohmann/json.hpp"

#include "GeneralUtils.h"

namespace nsMMF
{
    // !!! Do Not change the order to support MMF use case
    using MotorStatus = struct _MotorStatus
    {
        char MotorName[80]{}; // offset 0 : 80 byte to align to 8 bytes

        bool           NegLimHit{ false };   // 80
        bool           PosLimHit{ false };   // 81
        bool           Homed{ false };       // 82
        bool           ServoReady{ false };  // 83
        bool           ServoAlarm{ false };  // 84
        bool           InPosition{ false };  // 85
        bool           MtrOn{ false };       // 86
        bool           MtrCurOnOff{ false }; // 87 // array to store motor On/Off States before maintenance mode
        double         MtrPos{ 0. };         // 88
        double         PosErr{ 0. };         // 96
        unsigned short MotionStatus{ 0 };    // 104
        unsigned short Status{ 0 };          // 106
        int            MtrNo{ 0 };           // 108     // motor no wrt the type of card used
        int            MtrType{ 0 };         // 112     // servo or stepper, with or without encoder feedback
        int            MtrCurPos{ 0 };       // 116  // array to store motor position before maintenance mode

        // Assignment operator overload
        _MotorStatus& operator=(const _MotorStatus& rhs)
        {
            //
            strcpy_s(MotorName, rhs.MotorName);
            //
            NegLimHit    = rhs.NegLimHit;
            PosLimHit    = rhs.PosLimHit;
            Homed        = rhs.Homed;
            ServoReady   = rhs.ServoReady;
            ServoAlarm   = rhs.ServoAlarm;
            InPosition   = rhs.InPosition;
            MtrOn        = rhs.MtrOn;
            MtrCurOnOff  = rhs.MtrCurOnOff;
            MtrPos       = rhs.MtrPos;
            PosErr       = rhs.PosErr;
            MotionStatus = rhs.MotionStatus;
            Status       = rhs.Status;
            MtrNo        = rhs.MtrNo;
            MtrType      = rhs.MtrType;
            MtrCurPos    = rhs.MtrCurPos;

            return *this;
        }
    };
}

namespace nsMMF
{
    using namespace nlohmann;
    using namespace nsUtils;

    void from_json(const json& j, MotorStatus& x);
    void to_json(json& j, const MotorStatus& x);

    inline void from_json(const json& j, MotorStatus& x)
    {
        std::string name = j.at("MotorName").get<std::string>();
        strcpy_s(x.MotorName, name.c_str());

        getValue(j, "NegLimHit", x.NegLimHit);
        getValue(j, "PosLimHit", x.PosLimHit);
        getValue(j, "Homed", x.Homed);
        getValue(j, "ServoReady", x.ServoReady);
        getValue(j, "ServoAlarm", x.ServoAlarm);
        getValue(j, "InPosition", x.InPosition);
        getValue(j, "MtrOn", x.MtrOn);
        getValue(j, "MtrCurOnOff", x.MtrCurOnOff);
        getValue(j, "MtrPos", x.MtrPos);
        getValue(j, "PosErr", x.PosErr);
        getValue(j, "MotionStatus", x.MotionStatus);
        getValue(j, "Status", x.Status);
        getValue(j, "MtrNo", x.MtrNo);
        getValue(j, "MtrType", x.MtrType);
        getValue(j, "MtrCurPos", x.MtrCurPos);
    }

    inline void to_json(json& j, const MotorStatus& x)
    {
        j = nlohmann::json{
            { "MotorName", x.MotorName },
            { "NegLimHit", x.NegLimHit },
            { "PosLimHit", x.PosLimHit },
            { "Homed", x.Homed },
            { "ServoReady", x.ServoReady },
            { "ServoAlarm", x.ServoAlarm },
            { "InPosition", x.InPosition },
            { "MtrOn", x.MtrOn },
            { "MtrCurOnOff", x.MtrCurOnOff },
            { "MtrPos", x.MtrPos },
            { "PosErr", x.PosErr },
            { "MotionStatus", x.MotionStatus },
            { "Status", x.Status },
            { "MtrNo", x.MtrNo },
            { "MtrType", x.MtrType },
            { "MtrCurPos", x.MtrCurPos }
        };
    }

}