#include "fsm/Gate.h"

namespace Gate {

void State::enter(FSM* fsm) {}
void State::exit(FSM* fsm) {}
void State::Coin(FSM* fsm) { fsm->getContext()->error(getName(), "Coin"); }
void State::Pass(FSM* fsm) { fsm->getContext()->error(getName(), "Pass"); }

const char* LockedState::getName() const {  return "Locked"; }
void LockedState::enter(FSM* fsm) { fsm->getContext()->EnterLocked(fsm); }
void LockedState::exit(FSM* fsm) { fsm->getContext()->ExitLocked(fsm); }

void LockedState::Coin(FSM* fsm) {
  Context* context = fsm->getContext();
  fsm->setNewState(fsm->Unlocked());
  context->Unlock(fsm);
  exit(fsm);
  fsm->setState();
  fsm->getState()->enter(fsm);
}

void LockedState::Pass(FSM* fsm) {
  Context* context = fsm->getContext();
  fsm->setNewState(this);
  context->Alarm(fsm);
  if ( fsm->getNewState() != this ) {
    exit(fsm);
    fsm->setState();
    fsm->getState()->enter(fsm);
  } else {
    fsm->setState();
  }
}

LockedState FSM::Locked_;

const char* UnlockedState::getName() const {  return "Unlocked"; }
void UnlockedState::enter(FSM* fsm) { fsm->getContext()->EnterUnlocked(fsm); }
void UnlockedState::exit(FSM* fsm) { fsm->getContext()->ExitUnlocked(fsm); }

void UnlockedState::Coin(FSM* fsm) {
  Context* context = fsm->getContext();
  fsm->setNewState(this);
  context->ThankYou(fsm);
  if ( fsm->getNewState() != this ) {
    exit(fsm);
    fsm->setState();
    fsm->getState()->enter(fsm);
  } else {
    fsm->setState();
  }
}

void UnlockedState::Pass(FSM* fsm) {
  Context* context = fsm->getContext();
  fsm->setNewState(fsm->Locked());
  context->Lock(fsm);
  exit(fsm);
  fsm->setState();
  fsm->getState()->enter(fsm);
}

UnlockedState FSM::Unlocked_;

}

