#ifndef STATUSLIGHT_H
#define STATUSLIGHT_H

#include <Arduino.h>
#include <Component.h>
#include <macros.h>
#include <xmath.h>
#include <ModbusValue.h>
#include <Bridge.h>
#include "../enums.h"
#include "../config.h"

// COMPONENT_KEY_FEEDBACK_0 = 701,
// test relay::set <<701;2;64;701:set:1:0>>

class StatusLight : public Component, public ModbusValue<int>
{
public:
  StatusLight(Component *_owner,
              short _pin,
              short _id,
              short _addr)
      : last_blink(0),
        status_blink_TS(0),
        doBlink(false),
        pin(_pin),
        ModbusValue<int>(_addr, MB_FC::MB_FC_READ_REGISTERS),
        Component("Status", _id, Component::COMPONENT_DEFAULT, _owner)
  {
    doBlink = false;
    status_blink_TS = 0;
    last_blink = !digitalRead(pin);
    nFlags = SBI(nFlags, OBJECT_NET_CAPS::E_NCAPS_MODBUS);
    setRegisterMode(MB_REGISTER_MODE::E_MB_REGISTER_MODE_READ_WRITE);
  }

  void setBlink(bool blink)
  {
    doBlink = blink;
  }

  void on()
  {
     set(1);
  }

  void off()
  { 
    set(0);
  }

  short loop()
  {
    if (doBlink)
    {
      if (now - status_blink_TS > STATUS_BLINK_INTERVAL)
      {
        status_blink_TS = now;
        last_blink = !last_blink;
        digitalWrite(pin, last_blink);
      }
    }

    short val = netVal();
    if (val != digitalRead(pin))
    {
      onSet(val);
      set(val, 0);
    }

    return E_OK;
  }

  short set(short val0, short val1 = 0)
  {
    digitalWrite(pin, val0 ? HIGH : LOW);
    return E_OK;
  }

  short setup()
  {
    return E_OK;
  }

  short debug()
  {
    return info();
  }
  short info()
  {
    //Log.verboseln("StatusLight::debug - Addr=%d | NetVal=%d | Value=%d", addr, netVal(), digitalRead(pin));
    return E_OK;
  }

  void status_blink(bool blink)
  {
    if (!doBlink && blink)
    {
      blink_start_ts = millis();
    }
    doBlink = blink;
  }

  short onRegisterMethods(Bridge *bridge)
  {
    bridge->registerMemberFunction(id, this, C_STR("set"), (ComponentFnPtr)&StatusLight::set);
    bridge->registerMemberFunction(id, this, C_STR("info"), (ComponentFnPtr)&StatusLight::info);
  }

  short pin;
  millis_t status_blink_TS;
  bool doBlink;
  bool last_blink;
  millis_t blink_start_ts;
  millis_t max_blink_time;
};

#endif
