module main

import std.io
import vendor.raylib rl

let background_png = @embed("assets/background.png")
let bird_midflap_png = @embed("assets/bird_midflap.png")
let bird_upflap_png = @embed("assets/bird_upflap.png")
let bird_downflap_png = @embed("assets/bird_downflap.png")
let pipe_png = @embed("assets/pipe.png")
let pipe_head_png = @embed("assets/pipe_head.png")
let base_png = @embed("assets/base.png")

let die_wav = @embed("assets/die.wav")
let hit_wav = @embed("assets/hit.wav")
let point_wav = @embed("assets/point.wav")
let swoosh_wav = @embed("assets/swoosh.wav")
let wing_wav = @embed("assets/wing.wav")


let TextureType = type enum {
  Background,
  BirdMidflap,
  BirdUpflap,
  BirdDownflap,
  Pipe,
  PipeHead,
  Base,
}

let TextureType.format(self, writer: *mut dyn std.io.Writer) {
  std.io.wprint(writer, "{}", match self {
    .Background => "background",
    .BirdMidflap => "bird_midflap",
    .BirdUpflap => "bird_upflap",
    .BirdDownflap => "bird_downflap",
    .Pipe => "pipe",
    .PipeHead => "pipe_head",
    .Base => "base",
  })
}

let SoundType = type enum {
  Die,
  Hit,
  Point,
  Swoosh,
  Wing,
}

let SoundType.format(self, writer: *mut dyn std.io.Writer) {
  std.io.wprint(writer, "{}", match self {
    .Die => "die",
    .Hit => "hit",
    .Point => "point",
    .Swoosh => "swoosh",
    .Wing => "wing",
  })
}

let GameAssets = type struct {
  background:    rl.Texture2D,
  bird_midflap:  rl.Texture2D,
  bird_upflap:   rl.Texture2D,
  bird_downflap: rl.Texture2D,
  pipe:          rl.Texture2D,
  pipe_head:     rl.Texture2D,
  base:          rl.Texture2D,

  die:           rl.Sound,
  hit:           rl.Sound,
  point:         rl.Sound,
  swoosh:        rl.Sound,
  wing:          rl.Sound,
}
 
let load_texture_from_memory(texture: TextureType, png_data: []u8): rl.Texture2D {
  if @len(png_data) <= 0 {
    std.io.eprintln("Error: {} texture data length is zero", texture)
    panic("Failed to load texture from memory")
  }

  let image = rl.load_image_from_memory(".png", png_data[:], @len(png_data).(i32))
  if !rl.is_image_valid(image) {
    std.io.eprintln("Error: {} texture data is invalid", texture)
    panic("Failed to load texture from memory")
  }

  let texture = rl.load_texture_from_image(image)
  rl.unload_image(image)

  if !rl.is_texture_valid(texture) {
    std.io.eprintln("Error: {} texture could not be loaded", texture)
    panic("Failed to load texture from memory")
  }

  rl.set_texture_filter(texture, .Point)
  return texture
}

let load_sound_from_memory(sound: SoundType, wav_data: []u8): rl.Sound {
  if @len(wav_data) <= 0 {
    std.io.eprintln("Error: {} sound data length is zero", sound)
    panic("Failed to load sound from memory")
  }

  let wave = rl.load_wave_from_memory(".wav", wav_data[:], @len(wav_data).(i32))
  if !rl.is_wave_valid(wave) {
    std.io.eprintln("Error: {} sound data is invalid", sound)
    panic("Failed to load sound from memory")
  }

  let loaded_sound = rl.load_sound_from_wave(wave)
  rl.unload_wave(wave)

  if !rl.is_sound_valid(loaded_sound) {
    std.io.eprintln("Error: {} sound could not be loaded", sound)
    panic("Failed to load sound from memory")
  }

  return loaded_sound
}

let GameAssets.load() = GameAssets.{
  background    = load_texture_from_memory(.Background, background_png),
  bird_midflap  = load_texture_from_memory(.BirdMidflap, bird_midflap_png),
  bird_upflap   = load_texture_from_memory(.BirdUpflap, bird_upflap_png),
  bird_downflap = load_texture_from_memory(.BirdDownflap, bird_downflap_png),
  pipe          = load_texture_from_memory(.Pipe, pipe_png),
  pipe_head     = load_texture_from_memory(.PipeHead, pipe_head_png),
  base          = load_texture_from_memory(.Base, base_png),

  die           = load_sound_from_memory(.Die, die_wav),
  hit           = load_sound_from_memory(.Hit, hit_wav),
  point         = load_sound_from_memory(.Point, point_wav),
  swoosh        = load_sound_from_memory(.Swoosh, swoosh_wav),
  wing          = load_sound_from_memory(.Wing, wing_wav),
}

let GameAssets.unload(*self) {
  rl.unload_texture(self.background)
  rl.unload_texture(self.bird_midflap)
  rl.unload_texture(self.bird_upflap)
  rl.unload_texture(self.bird_downflap)
  rl.unload_texture(self.pipe)
  rl.unload_texture(self.pipe_head)
  rl.unload_texture(self.base)

  rl.unload_sound(self.die)
  rl.unload_sound(self.hit)
  rl.unload_sound(self.point)
  rl.unload_sound(self.swoosh)
  rl.unload_sound(self.wing)
}