#ifndef RELAY_H
#define RELAY_H

#include <ArduinoLog.h>
#include <osr-base.h>
#include <App.h>
#include <Component.h>
#include "types.h"
#include "../enums.h"
#include "../config.h"
#include <ModbusValue.h>

// test relay::set <<300;2;64;300:set:1:0>>
// test relay::info <<300;2;64;300:info:1:0>>
// test relay::info <<300;2;64;300:info:1:0>>

class Relay : public Component, public ModbusValue<bool>
{

public:
    Relay(
        Component *owner,
        short _pin,
        short _id,
        short _addr,
        short _val = 0) : ModbusValue<bool>(_addr, MB_FC::MB_FC_READ_COILS),
                       Component("MB_Relay", _id, Component::COMPONENT_DEFAULT, owner),
                       pin(_pin),
                       value(_val)
                       //registerMode(MB_REGISTER_MODE::E_MB_REGISTER_MODE_READ_WRITE)
    {
        //setFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG);
        SBI(nFlags, OBJECT_NET_CAPS::E_NCAPS_MODBUS);
        setRegisterMode(MB_REGISTER_MODE::E_MB_REGISTER_MODE_READ_WRITE);
    }

    short info(short val0, short val1)
    {
        Log.verboseln("Relay::info - Pin=%d | Key=%d | Addr=%d | Val=%d | NetVal=%d ", pin, id, addr, value, netVal());
        return E_OK;
    }
    short debug()
    {
        return info(0,0);
    }

    short setup()
    {
#ifdef PLATFORM_PORTENTA_H7_M7
        /*
        digital_outputs.setLatch();
        // Uncomment this line to set over current behavior of all
        // channels to auto retry mode instead of latch mode:
        // digital_outputs.setRetry();
        digital_outputs.set(pin, LOW);
        */
#endif
        return E_OK;
    }

    short set(int val)
    {
        value = val;
#ifdef PLATFORM_PORTENTA_H7_M7
        if (_value == 1)
        {
            digital_outputs.set(pin, HIGH);
            Log.verbose(F("Relay:set pin=%d value=%d" CR), pin, _value);
        }
        else
        {
            digital_outputs.set(pin, LOW);
            Log.verbose(F("Relay:set pin=%d value=%d" CR), pin, _value);
        }
#endif

#ifdef PLATFORM_CONTROLLINO_MEGA
        digitalWrite(pin, val ? HIGH : LOW);
#endif        
        if (netVal() != value)
        {
            onSet(val);
        }
        return val;
    }

    short onRegisterMethods(Bridge *bridge)
    {
        bridge->registerMemberFunction(id, this, C_STR("set"), (ComponentFnPtr)&Relay::set);
        bridge->registerMemberFunction(id, this, C_STR("info"), (ComponentFnPtr)&Relay::info);
        bridge->registerMemberFunction(id, this, C_STR("setFlag"), (ComponentFnPtr)&Relay::setFlag);
        //bridge->registerMemberFunction(id, this, C_STR("clearFlag"), (ComponentFnPtr)&Relay::clearFlag);
        return E_OK;
    }

    short loop()
    {
        bool val = netVal();
        if (val != value)
        {
            set(val);
        }
        return E_OK;
    }

    short pin;
    bool value;
};

#endif
