// Simon: watch which of the three pads lights up, then repeat the order with L / M / R.
// Every round the order gets one step longer.
#pragma once

const uint8_t SIMON_MAX = 32;

enum SimonPhase : uint8_t { SIMON_SHOW, SIMON_INPUT, SIMON_NICE };

struct SimonState {
  uint8_t order[SIMON_MAX];
  uint8_t len, pos, lit;
  uint8_t phase;
  uint16_t timer;                            // frames
};

void simon_init(SimonState &g) {
  memset(&g, 0, sizeof g);
  g.order[0] = random(3);
  g.len = 1;
  g.lit = 255;
  g.timer = 20;
}

void simon_update(SimonState &g) {
  if (g.timer > 0) {
    g.timer--;
  }

  if (g.phase == SIMON_SHOW) {
    if (g.timer > 0) {
      return;
    }

    if (g.lit != 255) {
      g.lit = 255;
      g.timer = 5;
      return;
    }

    if (g.pos < g.len) {
      g.lit = g.order[g.pos++];
      g.timer = g.len < 8 ? 14 : 9;
      return;
    }

    g.phase = SIMON_INPUT;
    g.pos = 0;
    g.timer = 0;
    return;
  }

  if (g.phase == SIMON_NICE) {
    if (g.timer == 0) {
      g.order[g.len++] = random(3);
      g.phase = SIMON_SHOW;
      g.pos = 0;
      g.timer = 10;
    }

    return;
  }

  if (g.timer == 0) {
    g.lit = 255;
  }

  for (uint8_t k = 0; k < KEY_COUNT; k++) {
    if (!key_tap[k]) {
      continue;
    }

    g.lit = k;
    g.timer = 6;

    if (k != g.order[g.pos]) {
      g.lit = g.order[g.pos];
      end_game();
      return;
    }

    if (++g.pos == g.len) {
      score = g.len;

      if (g.len == SIMON_MAX) {
        end_game();
        return;
      }

      g.phase = SIMON_NICE;
      g.timer = 20;
    }
  }
}

void simon_draw(SimonState &g) {
  for (uint8_t k = 0; k < KEY_COUNT; k++) {
    uint8_t x = 6 + k * 41;

    if (g.lit == k) {
      oled.drawRBox(x, 18, 34, 30, 4);
    } else {
      oled.drawRFrame(x, 18, 34, 30, 4);
    }
  }

  oled.setFont(u8g2_font_5x7_tr);
  oled.drawStr(0, 7, "ROUND");
  draw_number(g.len, 30, 7, false);
  oled.drawStr(84, 7, "BEST");
  draw_number(best, 127, 7, true);
  const char *label = g.phase == SIMON_SHOW ? "watch" : g.phase == SIMON_INPUT ? "your turn" : "nice!";
  text_center(label, 60);
}
