// src/render/loop.cpp
#include "loop.h"
#include "../assets/background_frame.h"
#include "player_positioning.h"
#include "background.h"
#include "mbed.h"
#include "player.h"
#include "../game/state.h"
#include "../game/animation.h"
#include "../hardware/uart.h"
#include "../assets/character_frames.h"

extern BufferedSerial serial_port;
extern DigitalOut led;

// Constants
constexpr int PLAYER_X = 9;
constexpr int PLAYER_Y = 6;

void draw_mask(const char *unused_filename, int shift, const char *text);

void render_loop(int speed) {
  WalkingState player_state;
  AnimationController animation;
  UartReader uart(serial_port);

  CharacterPosition pos = {PLAYER_X, PLAYER_Y};

  const char *bg_file = "background_dark_inverted.txt";
  bool need_redraw = false;

  while (true) {
    need_redraw = false;
    UartEvent uart_event = uart.poll();

    if (uart_event == UartEvent::MessageUpdate) {
      need_redraw = true;
    }

    if (uart_event == UartEvent::Triggered) {
      // start crawl frame for x time
      player_state.start_crawl();
      need_redraw = true;
    }

    // Check if crawl duration expired
    player_state.update();

    if (animation.tick(speed)) {
      need_redraw = true;
    }

    if (need_redraw) {
      draw_mask(bg_file, animation.get_shift(), uart.get_message());
      CharacterFrame player_frame = player_state.get_character_frame();

      CharacterPosition draw_pos = get_aligned_frame_position(pos, player_frame);
      draw_character(draw_pos.x, draw_pos.y, player_frame);

      // alternate between frame 0 and 1 when not crawling
      if (player_state.get_state() != PlayerState::Crawl1) {
	player_state.toggle_walk_frame();
      }

      ThisThread::sleep_for(50ms);
    }

    ThisThread::sleep_for(25ms);
  }
}
