local utils = require("lib_utils")
local config = utils.loadConfig('UISound.cfg')
local md = require("debugFunctions")

local UISound = {}
local active = {}
local pending = {}

function UISound.check(gamestate, stage)
  local key = mn.getMissionFilename():lower():gsub(".fs2", "")
  if gamestate == "GS_STATE_MAIN_MENU" then
    -- getNextMissionFilename() returns nil where getMissionFilename() returns an empty string
    key = (ca.getNextMissionFilename() or ""):lower():gsub(".fs2", "")
  end
  local entries = config[key] or {}
  local count = #entries
  
  for i=1, count do
    local entry = entries[i]
    local playstate = false
    local stopstate = false
	
    --Case specific to "catching up" if a mission required sounds to start at the mainhall before mission load
    if gamestate == "GS_STATE_LOAD_MISSION_MENU" and entry.state == "GS_STATE_MAIN_MENU" then
      if entry.action == "play" then
	    playstate = true
	  end
    end
    
    if entry.state == gamestate and entry.action == "play" then
      if entry.state == "GS_STATE_BRIEFING" and entry.stage ~= stage then
        playstate = false
      elseif entry.state == "GS_STATE_CMD_BRIEF" and entry.stage ~= stage then
        playstate = false
      else
        playstate = true
      end
    end
  
    if entry.state == gamestate and entry.action == "stop" then
      if entry.state == "GS_STATE_BRIEFING" and entry.stage ~= stage then
        stopstate = false
      elseif entry.state == "GS_STATE_CMD_BRIEF" and entry.stage ~= stage then
        stopstate = false
      else
        stopstate = true
      end
    end

    if playstate then
      if entry.delay then
        UISound.delay(entry.sound, entry.delay)
      else
        UISound.play(entry.sound)
      end
    end
    if stopstate then
      UISound.stop(entry.sound)
    end
  end
end

function UISound.onFrame()
  local now = time.getCurrentTime()
  for sound, when in pairs(pending) do
    local millisecondsElapsed = (now - when.initial):getSeconds() * 1000 
    --md.print("UISOUND: offset " .. tostring(when.offset) .. ", " .. tostring(millisecondsElapsed) .. " elapsed")
    if millisecondsElapsed >= when.offset then
      UISound.play(sound)
      pending[sound] = nil
    end
  end
end

function UISound.play(sound)
  if not sound then
    md.warningAlways("Found a UI sound entry without a sound")
  elseif not active[sound] then
    active[sound] = ad.playMusic(sound, 1, true)
  end
end

function UISound.delay(sound, delay)
  if not pending[sound] then
    pending[sound] = {
      ["initial"] = time.getCurrentTime(),
      ["offset"] = delay
    }
  end
end

function UISound.stop(sound)
  if active[sound] then
    ad.stopMusic(active[sound], true)
    active[sound] = nil
    pending[sound] = nil
  end
end

--If we're loading a mission and shouldn't have sounds that came from the mainhall then stop them
function UISound.maybeStopAll()

  local key = mn.getMissionFilename():lower():gsub(".fs2", "") 
  local entries = config[key] or {}
  local count = #entries
  
  local num = 0
  for i=1, count do
    local entry = entries[i]
	
	if entry.state == "GS_STATE_MAIN_MENU" then
	  num = num + 1
	end
  end

  if num == 0 and (utils.tableLength(active) > 0 or utils.tableLength(pending) > 0) then
    UISound.stopAll()
  end
end

function UISound.pauseAll(pause)
  for sound, handle in pairs(active) do
    ad.pauseMusic(handle, pause)
  end
end

function UISound.stopAll()
  for sound, handle in pairs(active) do
    ad.stopMusic(handle, true)
    active[sound] = nil
  end
  for sound, _ in pairs(pending) do
    pending[sound] = nil
  end
end

return UISound
