// https://forum.arduino.cc/t/solved-blinking-indicators/1327297
// https://wokwi.com/projects/415999787798480897

#include "proto_activities.h"

// activities

pa_activity (ButtonRecognizer, pa_ctx_tm(), int pin, bool& was_pressed, bool& was_released) {
  pinMode(pin, INPUT_PULLUP);

  pa_repeat {
    pa_await (digitalRead(pin) == LOW);
    was_pressed = true;
    pa_pause;
    was_pressed = false;
    pa_delay_ms (20); // debounce button press
    
    pa_await (digitalRead(pin) == HIGH);
    was_released = true;
    pa_pause;
    was_released = false;
    pa_delay_ms (20); // debounce button release
  }
} pa_end

pa_activity (Blink, pa_ctx_tm(), bool& show) {
  pa_every_ms (500) {
    show = !show;
  } pa_every_end
} pa_end

pa_activity (Delay_s, pa_ctx_tm(), int s) {
  pa_delay_s(s);
} pa_end

pa_activity (StateMachine, pa_ctx_tm(pa_use(Blink); pa_use(Delay_s)), bool was_pressed, bool was_released, bool& show) {
  pa_repeat {
    // Phase 1
    if (!was_pressed) {
      pa_when_abort (was_pressed, Blink, show);
    }

    // Phase 2
    show = true;
    pa_await (was_released);

    // Phase 3
    show = false;
    pa_when_abort (was_pressed, Delay_s, 3);
  }
} pa_end

pa_activity (Indicator, pa_ctx(), int pin, bool show) {
  pinMode(pin, OUTPUT);

  pa_always {
    digitalWrite(pin, show);
  } pa_always_end
} pa_end

pa_activity (Handler, pa_ctx(pa_co_res(3); pa_use(ButtonRecognizer); pa_use(StateMachine); pa_use(Indicator); bool was_pressed; bool was_released; bool show), 
                      int button, int indicator) {
  pa_co(3) {
    pa_with (ButtonRecognizer, button, pa_self.was_pressed, pa_self.was_released);
    pa_with (StateMachine, pa_self.was_pressed, pa_self.was_released, pa_self.show); 
    pa_with (Indicator, indicator, pa_self.show); 
  } pa_co_end
} pa_end

pa_activity (Main, pa_ctx(pa_co_res(2); pa_use_as(Handler, H1); pa_use_as(Handler, H2))) {
  pa_co(2) {
    pa_with_as (Handler, H1, 4, 11);
    pa_with_as (Handler, H2, 3, 10);
  } pa_co_end
} pa_end

pa_use(Main);

// setup and loop

void setup() {
  Serial.begin(115200);
}

void loop() {
  pa_tick(Main);
  delay(10);
}