#pragma once

#include <stdint.h>

enum __euler_stream_result : uint64_t {
  __EULER_SR_SUCCESS = 0,
  __EULER_SR_BAD_HANDLE,
  __EULER_SR_IO_ERROR,
  __EULER_SR_OUT_OF_BOUNDS,
  __EULER_SR_DOES_NOT_EXIST,
  __EULER_SR_NOT_A_REGULAR_FILE,
  __EULER_SR_NOT_AN_EXECUTABLE,
  __EULER_SR_NOT_WRITABLE,
  __EULER_SR_NOT_SEEKABLE,
  __EULER_SR_SOCKET_ID_ALREADY_IN_USE,
  __EULER_SR_SOCKET_ID_NOT_IN_USE,
  __EULER_SR_SOCKET_LISTENER_CLOSED,
  __EULER_SR_OTHER_END_CLOSED,
  __EULER_SR_ALREADY_EXISTS,
  __EULER_SR_NOT_SIZED
};

enum __euler_seek_from : uint8_t {
  __EULER_SF_BEGINNING = 0,
  __EULER_SF_END,
  __EULER_SF_CURRENT_POSITION
};

typedef uint64_t __euler_stream_handle;

extern "C" __euler_stream_result __euler_open_file(
  const char *path, uint64_t path_len, __euler_stream_handle &handle_out,
  bool allow_creation, bool only_allow_creation);

extern "C" [[noreturn]] void __euler_end_this_thread(int32_t exit_code);

extern "C" __euler_stream_result __euler_seek_stream(
  __euler_stream_handle handle, __euler_seek_from from, int64_t offset);

extern "C" __euler_stream_result __euler_set_stream_length(
  __euler_stream_handle handle, uint64_t new_length);

extern "C" void __euler_close_stream(__euler_stream_handle handle);

extern "C" __euler_stream_result __euler_get_stream_length(
  __euler_stream_handle handle, uint64_t &length_out);

extern "C" void *__euler_get_new_pages(uint64_t count);

extern "C" __euler_stream_result __euler_write_to_stream(
  __euler_stream_handle handle, uint64_t count, const void *buffer);

extern "C" __euler_stream_result __euler_read_from_stream(
  __euler_stream_handle handle, uint64_t count, void *buffer);

extern "C" uint32_t *__euler_get_framebuffer(
  uint32_t &width_out, uint32_t &height_out, uint32_t &pitch_out);

extern "C" uint32_t __euler_encode_color(uint8_t r, uint8_t g, uint8_t b);

enum __euler_mouse_buttons : uint8_t {
  __EULER_MB_LEFT = 1,
  __EULER_MB_RIGHT = 2,
  __EULER_MB_MIDDLE = 4
};

enum __euler_input_packet_type : uint8_t {
  __EULER_IPT_MOUSE = 1,
  __EULER_IPT_KEYBOARD = 2
};

extern "C" __euler_input_packet_type __euler_get_input_packet(
  __euler_mouse_buttons &buttons_out, int16_t &x_change_out,
  int16_t &y_change_out, uint32_t &keyboard_packet_out);
