#include "Stack5VHandler.h"

Stack5VHandler::Stack5VHandler(PowerSwitchIF& switcher) : switcher(switcher) {
  stackLock = MutexFactory::instance()->createMutex();
}

ReturnValue_t Stack5VHandler::deviceToOn(StackCommander commander, bool updateStates) {
  MutexGuard mg(stackLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
  if (updateStates) {
    updateInternalStates();
  }
  if (handlerState == HandlerState::SWITCH_PENDING) {
    return BUSY;
  }
  if (switchIsOn) {
    if (commander == StackCommander::PL_PCDU) {
      plPcduIsOn = true;
    } else {
      radSensorIsOn = true;
    }
    return returnvalue::OK;
  }

  handlerState = HandlerState::SWITCH_PENDING;
  targetState = true;
  return switcher.sendSwitchCommand(stackSwitch, PowerSwitchIF::SWITCH_ON);
}

ReturnValue_t Stack5VHandler::deviceToOff(StackCommander commander, bool updateStates) {
  MutexGuard mg(stackLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
  if (updateStates) {
    updateInternalStates();
  }
  // wait for our turn
  if (handlerState == HandlerState::SWITCH_PENDING) {
    return BUSY;
  }
  // If the switch is already off, we are done
  if (not switchIsOn) {
    if (commander == StackCommander::PL_PCDU) {
      plPcduIsOn = false;
    } else {
      radSensorIsOn = false;
    }
    return returnvalue::OK;
  }
  // If one device is still on, do not turn off the switch
  if ((commander == StackCommander::PL_PCDU and radSensorIsOn) or
      (commander == StackCommander::RAD_SENSOR and plPcduIsOn)) {
    return returnvalue::OK;
  }
  handlerState = HandlerState::SWITCH_PENDING;
  targetState = false;
  return switcher.sendSwitchCommand(stackSwitch, PowerSwitchIF::SWITCH_OFF);
}

bool Stack5VHandler::isSwitchOn() {
  MutexGuard mg(stackLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
  return updateInternalStates();
}

void Stack5VHandler::update() {
  MutexGuard mg(stackLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
  updateInternalStates();
}

bool Stack5VHandler::updateInternalStates() {
  if (switcher.getSwitchState(stackSwitch) == PowerSwitchIF::SWITCH_ON) {
    if (handlerState == HandlerState::SWITCH_PENDING and targetState) {
      handlerState = HandlerState::IDLE;
      switchIsOn = true;
    }
    return true;
  } else if (handlerState == HandlerState::SWITCH_PENDING and not targetState) {
    handlerState = HandlerState::IDLE;
    switchIsOn = false;
    radSensorIsOn = false;
    plPcduIsOn = false;
  }
  return false;
}