#ifndef POS3_ANALOG_H
#define POS3_ANALOG_H

#include <ArduinoLog.h>
#include "../config.h"
#include <osr-base.h>
#include <App.h>
#include <Component.h>
#include "types.h"
#include <xmath.h>
#include <ModbusValue.h>

class Pos3Analog : public Component, public ModbusValue<int>
{
public:
   enum POS3_DIRECTION
   {
      UP = 1,
      MIDDLE = 0,
      DOWN = 2,
      INVALID = 10
   };

   Pos3Analog(
       Component *owner,
       short _upPin, short _downPin,
       short _id,
       short _addr) : ModbusValue<int>(_addr, MB_FC::MB_FC_READ_REGISTERS),
                      Component("Pos3Analog", _id, Component::COMPONENT_DEFAULT, owner),
                      upPin(_upPin),
                      downPin(_downPin)
                      //registerMode(MB_REGISTER_MODE::E_MB_REGISTER_MODE_READ)
   {
      // setFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG);
      SBI(nFlags, OBJECT_NET_CAPS::E_NCAPS_MODBUS);
      setRegisterMode(MB_REGISTER_MODE::E_MB_REGISTER_MODE_READ);
   }

   short setup()
   {
      last_switch = read();
      return E_OK;
   }

   short info(short val0, short val1)
   {
      Log.verboseln("3PosAnalog::info - Pin-0=%d | Pin-1=%d | Key=%d | Addr=%d | Val=%d | NetVal=%d ", upPin, downPin, id, addr, value, netVal());
      return E_OK;
   }
   short debug()
   {
      return info(0, 0);
   }

   short loop()
   {
      if (now - last < ANALOG_SWITCH_READ_INTERVAL)
      {
         return E_OK;
      }
      last = now;
      int newDirection = read();
      if (newDirection != value)
      {
         last_switch = value;
      }
      value = newDirection;
      onSet(value);
      return value;
   }

   int last_switch = -1; // last switch position
   int value = -1;       // current switch position
   short upPin;
   short downPin;

   short onRegisterMethods(Bridge *bridge)
   {
      bridge->registerMemberFunction(id, this, C_STR("setFlag"), (ComponentFnPtr)&Pos3Analog::setFlag);
      //bridge->registerMemberFunction(id, this, C_STR("clearFlag"), (ComponentFnPtr)&Pos3Analog::clearFlag);
      bridge->registerMemberFunction(id, this, C_STR("info"), (ComponentFnPtr)&Pos3Analog::info);
      return E_OK;
   }

private:
   int read()
   {
      bool up = RANGE(analogRead(upPin), ANALOG_INPUT_MIN_THRESHOLD_0, 1000);
      bool down = RANGE(analogRead(downPin), ANALOG_INPUT_MIN_THRESHOLD_0, 1000);
      int newDirection = 0;
      if (up)
      {
         newDirection = POS3_DIRECTION::DOWN;
      }
      if (down)
      {
         newDirection = POS3_DIRECTION::UP;
      }
      if (!up && !down)
      {
         newDirection = POS3_DIRECTION::MIDDLE;
      }
      if (up && down)
      {
         newDirection = POS3_DIRECTION::INVALID;
      }
      return newDirection;
   }

   bool changed()
   {
      return last_switch != value;
   }

   bool clear()
   {
      last_switch = value;
      return E_OK;
   }

#ifdef HAS_MODBUS_REGISTER_DESCRIPTIONS
   String getRegisterDescription(short reg)
   {
      char buff[255];
      short s = snprintf(buff, 255, "- Read Position : Address=%d(%X) -> [Up:%d  Middle:%d Down:%d]", addr, addr, POS3_DIRECTION::UP, POS3_DIRECTION::MIDDLE, POS3_DIRECTION::DOWN);
      // snprintf (buff +s, 255 , "- Read Position : Address=%d(%X) -> [Up:%d  Middle:%d Down:%d] ", addr, addr, POS3_DIRECTION::UP, POS3_DIRECTION::MIDDLE, POS3_DIRECTION::DOWN);
      return String(buff);
   }
#endif
};

#endif
