local profile = require("core.profile")
local realmInfo
local LoadRealmInfo = function()
  if realmInfo == nil then
    realmInfo = require("design.RealmInfoLibrary")
  end
end
local GetRealmInfo = function()
  LoadRealmInfo()
  return realmInfo
end
local GetRealmFrame = function(realm)
  LoadRealmInfo()
  if realmInfo.frames[realm] then
    return realmInfo.frames[realm]
  else
    engine.Error("Attempting to get realm frame for invalid realm.")
  end
end
local TriggerOnce = function(variableName)
  if game.Level.GetVariable(variableName) == false then
    game.Level.SetVariable(variableName, true)
    return true
  end
  return false
end
local Trigger_WaterDrop01 = function()
  if TriggerOnce("_GBL_WaterDrop01Triggered") == false then
    engine.Error("Attempting to call Trigger_WaterDrop01 after _GBL_WaterDrop01Triggered has already been triggered.")
  end
end
local Trigger_WaterDrop02 = function()
  if TriggerOnce("_GBL_WaterDrop02Triggered") == false then
    engine.Error("Attempting to call Trigger_WaterDrop02 after _GBL_WaterDrop02Triggered has already been triggered.")
  end
end
local Trigger_DragonArrival = function()
  if TriggerOnce("_GBL_DragonArrivalTriggered") == false then
    engine.Error("Attempting to call Trigger_DragonArrival after _GBL_DragonArrivalTriggered has already been triggered.")
  end
end
local GetCurrentWaterLevel = function()
  if game.Level.GetVariable("_GBL_WaterDrop01Triggered") == false then
    return 0
  elseif game.Level.GetVariable("_GBL_WaterDrop02Triggered") == false then
    return 1
  else
    return 2
  end
end
local GetRealmFromValue = function(val)
  local realmEquivalent
  if val == 1 then
    realmEquivalent = "Muspelheim"
  elseif val == 2 then
    realmEquivalent = "Niflheim"
  elseif val == 3 then
    realmEquivalent = "Asgard"
  elseif val == 4 then
    realmEquivalent = "Svartalfheim"
  elseif val == 5 then
    realmEquivalent = "Helheim"
  elseif val == 6 then
    realmEquivalent = "Alfheim"
  elseif val == 7 then
    realmEquivalent = "Jotunheim"
  elseif val == 8 or val == 0 or val == -1 then
    realmEquivalent = "Midgard"
  end
  return realmEquivalent
end
local GetValueFromRealm = function(realm)
  if realm == "Muspelheim" then
    return 1
  elseif realm == "Niflheim" then
    return 2
  elseif realm == "Asgard" then
    return 3
  elseif realm == "Svartalfheim" then
    return 4
  elseif realm == "Helheim" then
    return 5
  elseif realm == "Alfheim" then
    return 6
  elseif realm == "Jotunheim" then
    return 7
  elseif realm == "Vanaheim" or realm == "Midgard" then
    return 8
  else
    return nil
  end
end
local GetSelectedRealm = function(levelName)
  local baseVar = "_SelectedRealm"
  if levelName then
    return GetRealmFromValue(game.Level.GetVariable(levelName .. baseVar))
  else
    return GetRealmFromValue(game.Level.GetVariable("_GBL" .. baseVar))
  end
end
local SetSelectedRealm = function(realm)
  local val = GetValueFromRealm(realm)
  if not val then
    engine.Error("Attempting to set invalid realm as selected realm.")
  else
    game.Level.SetVariable("_GBL_SelectedRealm", val)
  end
end
local GetCurrentRealm = function(levelName)
  local baseVar = "_CurrentRealm"
  if levelName then
    return GetRealmFromValue(game.Level.GetVariable(levelName .. baseVar))
  else
    return GetRealmFromValue(game.Level.GetVariable("_GBL" .. baseVar))
  end
end
local SetCurrentRealm = function(realm)
  local val = GetValueFromRealm(realm)
  if not val then
    engine.Error("Attempting to set invalid realm as current realm.")
  else
    game.Level.SetVariable("_GBL_CurrentRealm", val)
  end
end
local GetBridgePosition = function(levelName)
  local baseVar = "_BridgePosition"
  if levelName then
    return GetRealmFromValue(game.Level.GetVariable(levelName .. baseVar))
  else
    return GetRealmFromValue(game.Level.GetVariable("_GBL" .. baseVar))
  end
end
local GetBridgeAnimationFrame = function()
  return GetRealmFrame(GetBridgePosition())
end
local GetBridgeAnimationRate = function()
  return game.Level.GetVariable("_GBL_BridgeAnimationRate")
end
local GetCorrectedBridgeAnimRate = function(animObject, targetFrameOrRealm)
  local targetFrame
  if type(targetFrameOrRealm) == "string" then
    targetFrame = GetRealmFrame(targetFrameOrRealm)
  end
  local correctedAnimRate = GetBridgeAnimationRate()
  local diff = targetFrame - animObject.AnimFrame
  local halfFrame = animObject.AnimLengthFrames / 2
  if diff < 0 and diff > -halfFrame or 0 < diff and diff > halfFrame then
    correctedAnimRate = -1 * correctedAnimRate
  end
  return correctedAnimRate
end
local SetBridgePosition = function(realm, rate)
  SetSelectedRealm(realm)
  local val = GetValueFromRealm(realm)
  if not val then
    engine.Error("Attempting to set invalid realm as bridge position.")
  else
    if rate and type(rate) ~= "number" then
      engine.Error("Attempting to set an invalid bridge animation rate. Value is not a number, and is instead: " .. tostring(rate) .. " of value type " .. type(rate))
    end
    game.Level.SetVariable("_GBL_BridgeAnimationRate", rate or 1)
    game.Level.SetVariable("_GBL_BridgePosition", val)
  end
end
local DisplayEntityDebug = function(level, offset)
  if game.build.DEBUG == 1 and engine.IsDebug() then
    local t = {}
    local levelName = level.Name
    t.Title = levelName .. " Entity Variables"
    t.X = 200
    t.Y = 1 + offset
    local val = game.Level.GetVariable(levelName .. "_CompletedCineNumber")
    if val then
      table.insert(t, {
        "CompletedCineNumber: ",
        tostring(val)
      })
    end
    val = game.Level.GetVariable(levelName .. "_CurrentRealm")
    if val then
      table.insert(t, {
        "CurrentRealm: ",
        GetCurrentRealm(levelName) .. ": " .. tostring(val)
      })
    end
    val = game.Level.GetVariable(levelName .. "_SelectedRealm")
    if val then
      table.insert(t, {
        "SelectedRealm: ",
        GetSelectedRealm(levelName) .. ": " .. tostring(val)
      })
    end
    val = game.Level.GetVariable(levelName .. "_BridgePosition")
    if val then
      table.insert(t, {
        "BridgePosition: ",
        GetBridgePosition(levelName) .. ": " .. tostring(val)
      })
    end
    val = game.Level.GetVariable(levelName .. "_WaterDrop01Triggered")
    if val then
      table.insert(t, {
        "WaterDrop01Triggered: ",
        val
      })
    end
    val = game.Level.GetVariable(levelName .. "_WaterDrop02Triggered")
    if val then
      table.insert(t, {
        "WaterDrop02Triggered: ",
        val
      })
    end
    val = game.Level.GetVariable(levelName .. "_DragonArrivalTriggered")
    if val then
      table.insert(t, {
        "DragonArrivalTriggered: ",
        val
      })
    end
    engine.DrawDebugTable(t)
  end
end
return profile.WrapLibrary({
  GetRealmInfo = GetRealmInfo,
  GetRealmFrame = GetRealmFrame,
  Trigger_WaterDrop01 = Trigger_WaterDrop01,
  Trigger_WaterDrop02 = Trigger_WaterDrop02,
  Trigger_DragonArrival = Trigger_DragonArrival,
  GetCurrentWaterLevel = GetCurrentWaterLevel,
  GetRealmFromValue = GetRealmFromValue,
  GetValueFromRealm = GetValueFromRealm,
  GetSelectedRealm = GetSelectedRealm,
  SetSelectedRealm = SetSelectedRealm,
  GetCurrentRealm = GetCurrentRealm,
  SetCurrentRealm = SetCurrentRealm,
  GetBridgePosition = GetBridgePosition,
  SetBridgePosition = SetBridgePosition,
  GetBridgeAnimationFrame = GetBridgeAnimationFrame,
  GetBridgeAnimationRate = GetBridgeAnimationRate,
  GetCorrectedBridgeAnimRate = GetCorrectedBridgeAnimRate,
  DisplayEntityDebug = DisplayEntityDebug
})
