local profile = require("core.profile")
local savedCameraPos, savedCameraForward, savedPlayerPos, savedPlayerForward
local kMAGICLENGTH = 50
local kSPHERERADIUS = 0.2
local kPLAYERSPHERECOLOR = 255
local kCAMERASPHERECOLOR = 65280
local player
local kHIDEALLPOS = 0
local kDRAWPLAYERPOS = 1
local kDRAWCAMERAPOS = 2
local kDRAWPLAYERANDCAMERAPOS = 3
local kDRAWALLPOS = kDRAWPLAYERANDCAMERAPOS
local kENDOFDRAWSTATE = kDRAWALLPOS
local dbgDrawState
local tButtonDownState = {}
local bUpReleased, bLeftReleased, bRightReleased, bDownReleased, bCircleReleased, bCrossReleased, bTriangleReleased, bSquareReleased
local bPrintButtonRelease = false
local dbg_LockonCameraPos, dbg_LockonTargetPos, dbg_LockonBottomPos, dbg_OrbitForward
local dbg_EasingTableName = ""
local dbg_EasingStatusColor = 0
local SetLockonCameraPos = function(position)
  dbg_LockonCameraPos = position
end
local GetLockonCameraPos = function()
  return dbg_LockonCameraPos
end
local SetLockonTargetPos = function(position)
  dbg_LockonTargetPos = position
end
local GetLockonTargetPos = function()
  return dbg_LockonTargetPos
end
local SetLockonBottomPos = function(position)
  dbg_LockonBottomPos = position
end
local GetLockonBottomPos = function()
  return dbg_LockonBottomPos
end
local SetOrbitForward = function(vector)
  dbg_OrbitForward = vector
end
local GetOrbitForward = function()
  return dbg_OrbitForward
end
local CameraDebugLibraryInit = function()
  player = game.Player.FindPlayer()
  savedCameraPos = player:GetWorldPosition()
  dbgDrawState = kHIDEALLPOS
  savedPlayerPos = player:GetWorldPosition()
  savedPlayerForward = player:GetWorldForward()
  savedCameraPos = savedPlayerPos
  savedCameraForward = savedPlayerForward
  tButtonDownState.UpDown = false
  tButtonDownState.LeftDown = false
  tButtonDownState.RightDown = false
  tButtonDownState.DownDown = false
  bUpReleased = false
  bLeftReleased = false
  bRightReleased = false
  bDownReleased = false
  bCircleReleased = false
  bCrossReleased = false
  bTriangleReleased = false
  bSquareReleased = false
end
local bPrintOverride = false
local MyPrint = function(passedstring, bPrint)
  bPrint = bPrint or false
  if bPrint == true or bPrintOverride then
    print(passedstring)
  end
end
local SetDebugCameraPosition = function(position)
  savedCameraPos = position
end
local SetDebugCameraForward = function(vector)
  savedCameraForward = vector
end
local SetDebugPlayerPosition = function(position)
  savedPlayerPos = position
end
local SetDebugPlayerForward = function(vector)
  savedPlayerForward = vector
end
local SetDownStateOfButton = function(name, bVal)
  tButtonDownState[name] = bVal
end
local GetDownStateOfButton = function(name)
  return tButtonDownState[name]
end
local DrawBetterSphere = function(position, radius, hexcolor, durationinseconds)
  local duration = durationinseconds or 0
  engine.DrawCircle(position, radius, engine.Vector.New(0, 0, 1), hexcolor, duration)
  engine.DrawCircle(position, radius, engine.Vector.New(0, 1, 0), hexcolor, duration)
  engine.DrawCircle(position, radius, engine.Vector.New(1, 0, 0), hexcolor, duration)
end
local CheckButtonState = function()
  if player.Pad.UpDown == false and GetDownStateOfButton("UpDown") == true then
    bUpReleased = true
  end
  if player.Pad.LeftDown == false and GetDownStateOfButton("LeftDown") == true then
    bLeftReleased = true
  end
  if player.Pad.RightDown == false and GetDownStateOfButton("RightDown") == true then
    bRightReleased = true
  end
  if player.Pad.DownDown == false and GetDownStateOfButton("DownDown") == true then
    bDownReleased = true
  end
  if player.Pad.CircleDown == false and GetDownStateOfButton("CircleDown") == true then
    bCircleReleased = true
  end
  if player.Pad.CrossDown == false and GetDownStateOfButton("CrossDown") == true then
    bCrossReleased = true
  end
  if player.Pad.TriangleDown == false and GetDownStateOfButton("TriangleDown") == true then
    bTriangleReleased = true
  end
  if player.Pad.SquareDown == false and GetDownStateOfButton("SquareDown") == true then
    bSquareReleased = true
  end
  if player.Pad.UpDown == true then
    SetDownStateOfButton("UpDown", true)
  end
  if player.Pad.LeftDown == true then
    SetDownStateOfButton("LeftDown", true)
  end
  if player.Pad.RightDown == true then
    SetDownStateOfButton("RightDown", true)
  end
  if player.Pad.DownDown == true then
    SetDownStateOfButton("DownDown", true)
  end
  if player.Pad.CircleDown == true then
    SetDownStateOfButton("CircleDown", true)
  end
  if player.Pad.CrossDown == true then
    SetDownStateOfButton("CrossDown", true)
  end
  if player.Pad.TriangleDown == true then
    SetDownStateOfButton("TriangleDown", true)
  end
  if player.Pad.SquareDown == true then
    SetDownStateOfButton("SquareDown", true)
  end
end
local UpdateButtonState = function()
  if bUpReleased == true then
    MyPrint("UpDown is TRUE", bPrintButtonRelease)
    bUpReleased = false
    SetDownStateOfButton("UpDown", false)
  end
  if bLeftReleased == true then
    MyPrint("LeftDown is TRUE", bPrintButtonRelease)
    bLeftReleased = false
    SetDownStateOfButton("LeftDown", false)
  end
  if bRightReleased == true then
    MyPrint("RightDown is TRUE", bPrintButtonRelease)
    bRightReleased = false
    SetDownStateOfButton("RightDown", false)
  end
  if bDownReleased == true then
    MyPrint("DownDown is TRUE", bPrintButtonRelease)
    bDownReleased = false
    SetDownStateOfButton("DownDown", false)
  end
  if bCircleReleased == true then
    MyPrint("CircleDown is TRUE", bPrintButtonRelease)
    bCircleReleased = false
    SetDownStateOfButton("CircleDown", false)
  end
  if bCrossReleased == true then
    MyPrint("CrossDown is TRUE", bPrintButtonRelease)
    bCrossReleased = false
    SetDownStateOfButton("CrossDown", false)
  end
  if bTriangleReleased == true then
    MyPrint("TriangleDown is TRUE", bPrintButtonRelease)
    bTriangleReleased = false
    SetDownStateOfButton("TriangleDown", false)
  end
  if bSquareReleased == true then
    MyPrint("SquareDown is TRUE", bPrintButtonRelease)
    bSquareReleased = false
    SetDownStateOfButton("SquareDown", false)
  end
end
local IsUpReleased = function()
  return bUpReleased
end
local IsLeftReleased = function()
  return bLeftReleased
end
local IsRightReleased = function()
  return bRightReleased
end
local IsDownReleased = function()
  return bDownReleased
end
local IsCircleReleased = function()
  return bCircleReleased
end
local IsCrossReleased = function()
  return bCrossReleased
end
local IsTriangleReleased = function()
  return bTriangleReleased
end
local IsSquareReleased = function()
  return bSquareReleased
end
local UpdateDebugDraws = function()
  if bUpReleased then
    dbgDrawState = dbgDrawState + 1
    if dbgDrawState > kENDOFDRAWSTATE then
      dbgDrawState = kHIDEALLPOS
    end
  end
  if bDownReleased then
    engine.DrawLine(savedCameraPos, savedCameraPos + savedCameraForward, kCAMERASPHERECOLOR, 2)
    engine.DrawLine(savedPlayerPos, savedPlayerPos + savedPlayerForward, kPLAYERSPHERECOLOR, 2)
  end
  if bLeftReleased then
    savedPlayerPos = player:GetWorldPosition()
    savedPlayerForward = player:GetWorldForward() * kMAGICLENGTH
  end
  if bRightReleased then
    savedCameraPos = game.Camera.GetOrbitPosition()
    savedCameraForward = game.Camera.GetOrbitForward()
  end
  if bCircleReleased then
    MyPrint("emptyfornow")
  end
  if bCrossReleased then
    MyPrint("emptyfornow")
  end
  if dbgDrawState == kDRAWPLAYERPOS then
    DrawBetterSphere(savedPlayerPos, kSPHERERADIUS, kPLAYERSPHERECOLOR)
  elseif dbgDrawState == kDRAWCAMERAPOS then
    DrawBetterSphere(savedCameraPos, kSPHERERADIUS, kCAMERASPHERECOLOR)
  elseif dbgDrawState == kDRAWPLAYERANDCAMERAPOS then
    DrawBetterSphere(savedPlayerPos, kSPHERERADIUS, kPLAYERSPHERECOLOR)
    DrawBetterSphere(savedCameraPos, kSPHERERADIUS, kCAMERASPHERECOLOR)
  end
end
local RotateOnAxis = function(vectorA, theta)
  theta = math.rad(theta)
  local rotationMatrix = {
    {
      1,
      0,
      0
    },
    {
      0,
      math.cos(theta),
      -math.sin(theta)
    },
    {
      0,
      math.sin(theta),
      math.cos(theta)
    }
  }
  local outputVector = {
    0,
    0,
    0
  }
  local rotatedVector = engine.Vector.New(0, 0, 0)
  outputVector[1] = rotationMatrix[1][1] * vectorA.x + rotationMatrix[1][2] * vectorA.y + rotationMatrix[1][3] * vectorA.z
  outputVector[2] = rotationMatrix[2][1] * vectorA.x + rotationMatrix[2][2] * vectorA.y + rotationMatrix[2][3] * vectorA.z
  outputVector[3] = rotationMatrix[3][1] * vectorA.x + rotationMatrix[3][2] * vectorA.y + rotationMatrix[3][3] * vectorA.z
  rotatedVector.x = outputVector[1]
  rotatedVector.y = outputVector[2]
  rotatedVector.z = outputVector[3]
  return rotatedVector
end
local DrawAngledVector = function(forwardvector, angleDegrees)
  local angle = math.rad(angleDegrees)
  local x = forwardvector.x
  local y = math.cos(angle) * forwardvector.y + math.sin(angle) * forwardvector.z
  local z = math.sin(angle) * -forwardvector.y + math.cos(angle) * forwardvector.z
  local rotatedvector = engine.Vector.New(x, y, z)
  engine.DrawLine(savedCameraPos, savedCameraPos + savedCameraForward * 10, 255, 8)
  engine.DrawLine(savedCameraPos, savedCameraPos + rotatedvector * 10, 16711680, 8)
end
local GetRGBFromHex = function(hexValue, bOverride)
  local red = bit32.band(hexValue, 16711680)
  red = bit32.rshift(red, 16)
  local green = bit32.band(hexValue, 65280)
  green = bit32.rshift(green, 8)
  local blue = bit32.band(hexValue, 255)
  return red, green, blue
end
local DBG_DisplayEasingDebugTable = function()
  local debugtable = {}
  debugtable[1] = {"..."}
  local red, green, blue = GetRGBFromHex(dbg_EasingStatusColor)
  local tableColor = engine.Vector.New(red, green, blue)
  local titleName = dbg_EasingTableName
  debugtable.Title = titleName
  debugtable.TitleColor = tableColor
  debugtable.TitleAlpha = 255
  debugtable.X = 230
  debugtable.Y = 10
  engine.DrawDebugTable(debugtable)
end
local DBG_SetEasingTableName = function(name)
  dbg_EasingTableName = name
end
local DBG_SetStatusColor = function(number)
  local color_ready = 34816
  local color_inprogress = 16711680
  local color_blocked = 16776960
  if number == 1 then
    dbg_EasingStatusColor = color_ready
  elseif number == 2 then
    dbg_EasingStatusColor = color_inprogress
  elseif number == 3 then
    dbg_EasingStatusColor = color_blocked
  end
end
return profile.WrapLibrary({
  SetLockonCameraPos = SetLockonCameraPos,
  GetLockonCameraPos = GetLockonCameraPos,
  SetLockonTargetPos = SetLockonTargetPos,
  GetLockonTargetPos = GetLockonTargetPos,
  SetLockonBottomPos = SetLockonBottomPos,
  GetLockonBottomPos = GetLockonBottomPos,
  SetOrbitForward = SetOrbitForward,
  GetOrbitForward = GetOrbitForward,
  CameraDebugLibraryInit = CameraDebugLibraryInit,
  MyPrint = MyPrint,
  SetDebugCameraPosition = SetDebugCameraPosition,
  SetDebugCameraForward = SetDebugCameraForward,
  SetDebugPlayerPosition = SetDebugPlayerPosition,
  SetDebugPlayerForward = SetDebugPlayerForward,
  DrawBetterSphere = DrawBetterSphere,
  CheckButtonState = CheckButtonState,
  UpdateButtonState = UpdateButtonState,
  IsUpReleased = IsUpReleased,
  IsLeftReleased = IsLeftReleased,
  IsRightReleased = IsRightReleased,
  IsDownReleased = IsDownReleased,
  IsCircleReleased = IsCircleReleased,
  IsCrossReleased = IsCrossReleased,
  IsTriangleReleased = IsTriangleReleased,
  IsSquareReleased = IsSquareReleased,
  UpdateDebugDraws = UpdateDebugDraws,
  DrawAngledVector = DrawAngledVector,
  RotateOnAxis = RotateOnAxis,
  GetRGBFromHex = GetRGBFromHex,
  DBG_DisplayEasingDebugTable = DBG_DisplayEasingDebugTable,
  DBG_SetEasingTableName = DBG_SetEasingTableName,
  DBG_SetStatusColor = DBG_SetStatusColor
})
