#include "Behaviors/StateMachine.h"
#include "Events/EventBase.h"

$nodeclass CombinationLock : StateNode {
    $nodeclass ComboSequence : StateNode : doStart {
        cout << "Start" << endl;
        postStateSignal<int>(1);
    }

    $nodeclass CheckButton : StateNode : doStart {
        size_t button = event->getSourceID();
        EventBase::EventTypeID_t type = event->getTypeID();
        if(type == EventBase::activateETID) {
            postStateSignal<int>(button);
            cout << "Sensed the " << button << " button." << endl;
        }
    }

    $nodeclass Combination(int a, int b, int c, int d, int e) : StateNode {
        static int count;
        static bool entry_good;
        virtual void doStart() {
            int digit = extractSignal<int>(event);
            bool signal = true;
            ++count;
            cout << "Combination at count " << count << "." << endl;
            switch(count) {
            case 1:
                entry_good = (a == digit);
                break;
            case 2:
                entry_good = entry_good && (b == digit);
                break;
            case 3:
                entry_good = entry_good && (c == digit);
                break;
            case 4:
                entry_good = entry_good && (d == digit);
                break;
            case 5:
                entry_good = entry_good && (e == digit);
                if(entry_good) {
                    cout << "Unlocked!" << endl;
                }
                signal = false;
                count = 0;
                break;
            default:
                break;
            }
            postStateSignal<bool>(signal);
        }
    }

    $setupmachine {
        start_combo: ComboSequence
        check_button: CheckButton
        combination: Combination(1, 0, 1, 1, 0)

        start_combo =B=> check_button
        check_button =S<int>=> combination
        check_button =B=> check_button
        combination =S<bool>(true)=> check_button
        combination =S<bool>(false)=> start_combo
    }
}

int CombinationLock::Combination::count = 0;
bool CombinationLock::Combination::entry_good = false;
REGISTER_BEHAVIOR(CombinationLock);
