///|
/// Private lifecycle ledger shared by desktop coordinator adapters.
///
/// The public window registry describes application-visible state. This
/// ledger describes resource ownership, so a late close/detach callback cannot
/// run native teardown twice for the same backend window.
priv enum WindowLifecycleState {
  Active
  Closing
  Closed
}

///|
priv struct WindowLifecycleEntry {
  id : @backend_host.WindowId
  mut state : WindowLifecycleState
}

///|
priv struct WindowLifecycleCore {
  mut entries : Array[WindowLifecycleEntry]
}

///|
fn WindowLifecycleCore::new() -> WindowLifecycleCore {
  { entries: [], }
}

///|
/// Register one resource owner. Duplicate active registrations are rejected.
fn WindowLifecycleCore::register(
  self : WindowLifecycleCore,
  id : @backend_host.WindowId,
) -> Bool {
  for entry in self.entries {
    if entry.id == id {
      return false
    }
  }
  self.entries.push({ id, state: Active, })
  true
}

///|
/// Begin teardown exactly once and claim the teardown effect.
fn WindowLifecycleCore::begin_close(
  self : WindowLifecycleCore,
  id : @backend_host.WindowId,
) -> Bool {
  for entry in self.entries {
    if entry.id == id {
      match entry.state {
        Active => {
          entry.state = Closing
          return true
        }
        Closing | Closed => return false
      }
    }
  }
  false
}

///|
/// Mark a claimed teardown complete; late callbacks remain harmless.
fn WindowLifecycleCore::finish_close(
  self : WindowLifecycleCore,
  id : @backend_host.WindowId,
) -> Bool {
  for entry in self.entries {
    if entry.id == id {
      match entry.state {
        Closing => {
          entry.state = Closed
          return true
        }
        Closed => return false
        Active => return false
      }
    }
  }
  false
}

///|
/// Roll back a registration when native window creation or binding fails.
fn WindowLifecycleCore::rollback(
  self : WindowLifecycleCore,
  id : @backend_host.WindowId,
) -> Bool {
  let before = self.entries.length()
  self.entries = self.entries.filter(entry => entry.id != id)
  before != self.entries.length()
}