// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
pub struct LoadedFolder {
  handles : Array[Handle[Image]]
}

///|
pub(all) enum AssetEvent[T] {
  Added(Handle[T])
  Modified(Handle[T])
  Removed(Handle[T])
  LoadedWithDependencies(Handle[T])
}

///|
pub fn host_asset_load_folder(path : String) -> Int {
  @core.with_host_string_id(path, fn(path_id) {
    host_asset_load_folder_id(path_id)
  })
}

///|
fn host_asset_load_folder_id(path_id : Int) -> Int = "mgstudio_host" "asset_load_folder"

///|
pub fn host_asset_poll_loaded_folder_event_kind() -> Int = "mgstudio_host" "asset_poll_loaded_folder_event_kind"

///|
pub fn host_asset_poll_loaded_folder_event_id() -> Int = "mgstudio_host" "asset_poll_loaded_folder_event_id"

///|
pub fn host_asset_loaded_folder_handles_len(folder_id : Int) -> Int = "mgstudio_host" "asset_loaded_folder_handles_len"

///|
pub fn host_asset_loaded_folder_handles_get(
  folder_id : Int,
  index : Int,
) -> Int = "mgstudio_host" "asset_loaded_folder_handles_get"

///|
let loaded_folder_assets : Ref[Assets[LoadedFolder]] = Ref::new(Assets::new())

///|
let loaded_folder_events : Ref[Array[AssetEvent[LoadedFolder]]] = Ref::new([])

///|
pub fn AssetServer::load_folder(
  self : AssetServer,
  path : String,
) -> Handle[LoadedFolder] {
  let host_id = host_asset_load_folder(path)
  self.paths.push(path)
  Handle::new(host_id)
}

///|
pub fn asset_get_loaded_folder(handle : Handle[LoadedFolder]) -> LoadedFolder? {
  loaded_folder_assets.val.get(handle)
}

///|
pub fn asset_loaded_folder_drain_events() -> Array[AssetEvent[LoadedFolder]] {
  let out : Array[AssetEvent[LoadedFolder]] = []
  for ev in loaded_folder_events.val {
    out.push(ev)
  }
  loaded_folder_events.val.clear()
  out
}

///|
pub fn asset_update_loaded_folders() -> Unit {
  // Ensure any leftover internal asset events don't leak between frames.
  loaded_folder_assets.val.drain_events() |> ignore
  while true {
    let kind = host_asset_poll_loaded_folder_event_kind()
    if kind < 0 {
      break
    }
    let host_id = host_asset_poll_loaded_folder_event_id()
    let handle = Handle::new(host_id)
    if kind == 3 {
      let n = host_asset_loaded_folder_handles_len(host_id)
      let handles : Array[Handle[Image]] = []
      for j in 0.. ignore
      for ev in loaded_folder_assets.val.drain_events() {
        loaded_folder_events.val.push(ev)
      }
      loaded_folder_events.val.push(LoadedWithDependencies(handle))
    } else if kind == 0 {
      loaded_folder_assets.val.insert(handle, LoadedFolder::{ handles: [] })
      |> ignore
      for ev in loaded_folder_assets.val.drain_events() {
        loaded_folder_events.val.push(ev)
      }
    } else if kind == 1 {
      let n = host_asset_loaded_folder_handles_len(host_id)
      let handles : Array[Handle[Image]] = []
      for j in 0.. ignore
      for ev in loaded_folder_assets.val.drain_events() {
        loaded_folder_events.val.push(ev)
      }
    } else if kind == 2 {
      loaded_folder_assets.val.remove(handle) |> ignore
      for ev in loaded_folder_assets.val.drain_events() {
        loaded_folder_events.val.push(ev)
      }
    }
  }
}