#include "input.hpp"
#include "main.hpp"

[[noreturn]] void input_thread_main() {

  euler::syscall::set_thread_name("input thread");

  window *window_being_moved = 0;
  bool was_mouse_down_before = false;

  while (true) {

    auto result = euler::syscall::get_input_packet();
    if (std::holds_alternative<euler::syscall::mouse_packet>(result)) {
      auto packet = std::get<euler::syscall::mouse_packet>(result);

      r->lock();

      int old_x, old_y;
      r->get_cursor(old_x, old_y);
      r->bump_cursor(packet.x_changed, packet.y_changed);
      int new_x, new_y;
      r->get_cursor(new_x, new_y);

      if (window_being_moved != 0) {
        if (r->windows.size() == 0 || r->windows.back() != window_being_moved)
          window_being_moved = 0;
        else {
          r->windows.back()->x += new_x - old_x;
          r->windows.back()->y += new_y - old_y;
          if (!packet.left_button_down)
            window_being_moved = 0;
        }
      }

      else if (packet.left_button_down && !was_mouse_down_before)
        for (auto it = r->windows.rbegin(); it != r->windows.rend(); ++it)
          if (new_x >= (*it)->x && new_y >= (*it)->y &&
              new_x < (*it)->x + (*it)->contents_with_decorations. width &&
              new_y < (*it)->y + (*it)->contents_with_decorations.height) {
            r->move_window_to_front(--it.base());
            //it is now invalidated, but our window is now r->windows.back()
            if (new_y < r->windows.back()->y + window::title_height)
              window_being_moved = r->windows.back();
            break;
          }

      r->unlock();
      r->dispatch_render();

      was_mouse_down_before = packet.left_button_down;

    }

  }

}
