local profile = require("core.profile")
local thunk = require("core.thunk")
local DL = require("design.DesignerLibrary")
local helper = require("son.helper")
local PL = require("design.PrototypeLibrary")
local quiver
local InputSetup = function(ai, global, constants)
  thunk.Install("OnCommandSonStart", function(go, inputType)
    if ai.IsAvailableInLevel and not ai:IsAvailableInLevel() then
      return
    end
    if ai:HasMarker("InVendor") == true or ai:HasMarker("BossDoNotShoot") or constants.doingPostUpAutonomousShot then
      return
    end
    if gVFSDebugInputCommand.value == true then
      if inputType == "Tap" then
        constants.inputDebugPressed = true
        ai:TriggerMoveEvent("" .. gVFSDebugInputCommandMoveEvent.value)
      else
        constants.inputDebugPressed = false
      end
      return
    end
    local attackType = "None"
    if ai.OwnedPOI ~= nil then
      attackType = ai.OwnedPOI:FindLuaTableAttribute("SonAttackType")
    end
    if ai.OwnedPOI then
      if attackType ~= "CommandShot" and attackType ~= "Both" then
        if inputType == "Regular" or inputType == "Charged" or not ai.OwnedPOI.Type == "ContextAction" then
          return PuppeteerInputLogic(ai, global, constants, inputType)
        end
      elseif (ai.OwnedPOI:GetStageName() == "Approach" or ai.OwnedPOI:GetStageName() == "ApproachStart") and ai.OwnedPOI.ResetApproachTimer ~= nil then
        ai.OwnedPOI:ResetApproachTimer()
      end
    end
    if ai.IsAvailableForCombat and not ai:IsAvailableForCombat() then
      if ai:HasMarker("Son_KnockedDown") then
        if ai:HasMarker("Stunned") then
          game.Audio.PlayBanterNonCritical("SonCantFire")
        else
          game.Audio.PlayBanterNonCritical("SonCantFire_Short")
        end
      end
      return
    end
    if global.currentState == "InCombat" then
      return InCombatInputLogic(ai, global, constants, inputType)
    end
    if global.currentState == "EnterCombat" then
      return InCombatInputLogic(ai, global, constants, inputType)
    end
    if global.currentState == "PreCombat" then
      return InCombatInputLogic(ai, global, constants, inputType)
    end
    if global.currentState == "PostCombat" then
      return InCombatInputLogic(ai, global, constants, inputType)
    end
    if global.currentState == "Idle" then
      return InCombatInputLogic(ai, global, constants, inputType)
    end
  end)
end
function PuppeteerInputLogic(ai, global, constants, inputType)
  if global.POIInfo.useThisPOI ~= nil then
    if global.POIInfo.useThisPOI.Type == "CommandShotEnabled" then
      local targetOfPlayer = helper.returnBestPlayerTargetCreature(global, true)
      if targetOfPlayer == nil then
        local enemiesNearby = ai:FindEnemies(10)
        if 0 < #enemiesNearby then
          targetOfPlayer = enemiesNearby[1]
        end
      end
      global.selfAI:SetCombatTarget(targetOfPlayer)
      global.bCommand_Action = false
      ai:TriggerMoveEvent("kLE_E3TrollShootArrow")
      global.sTargetMode = "KratosTarget"
    elseif global.POIInfo.useThisPOI.Type == "TurretMode" then
      local targetOfPlayer = helper.returnBestPlayerTargetCreature(global, true)
      global.selfAI:SetCombatTarget(targetOfPlayer)
      global.POIInfo.useThisPOI:SendEvent("EndSyncAndDisable")
      global.bCommand_Action = false
      if targetOfPlayer ~= nil then
        global.selfAI:ForceMove("BRA_CrouchShot00_Rune")
      else
        global.selfAI:ForceMove("BRA_CrouchShot00_RuneNoTarget")
      end
      global.sTargetMode = "KratosTarget"
    elseif global.POIInfo.useThisPOI.Type == "ToggleActivate" or global.POIInfo.useThisPOI.Type == "ToggleDeactivate" then
      if global.poistates_poitoggle.toggleTimer < global.poistates_poitoggle.toggleTimerMax then
        return
      end
      if DL.CheckCreatureContext(ai:GetContext(), "TOGGLE_ON") then
        ai:TriggerMoveEvent("deactivateLoop")
        global.POIInfo.useThisPOI:SendEvent("deactivated")
      elseif DL.CheckCreatureContext(ai:GetContext(), "TOGGLE_OFF") then
        ai:TriggerMoveEvent("activateLoop")
        global.POIInfo.useThisPOI:SendEvent("activated")
      end
      global.poistates_poitoggle.toggleTimer = 0
    elseif global.POIInfo.useThisPOI.Type == "ActivateOneOff" then
      global.POIInfo.useThisPOI:SendEvent("activated")
    elseif global.POIInfo.useThisPOI.Type == "CrystalThrow" then
      global.POIInfo.useThisPOI:SendEvent("kESonThrowCrystal")
      ai:TriggerMoveEvent("LEThrowCrystal")
    end
  end
end
function PreCombatInputLogic(ai, global, constants, inputType)
end
function PostCombatInputLogic(ai, global, constants, inputType)
end
function IdleInputLogic(ai, global, constants, inputType)
end
function SetArrowColor(data)
  if data == 0 then
    local shockMaterialParams = {
      Color = engine.Vector.New(0, 0.4, 0.8)
    }
    PL.SetAnimatedMaterialAttributes(quiver, "feather", "base", shockMaterialParams)
    PL.SetAnimatedMaterialAttributes(quiver, "feather01", "base", shockMaterialParams)
    PL.SetAnimatedMaterialAttributes(quiver, "feather02", "base", shockMaterialParams)
  elseif data == 1 then
    local lightMaterialParams = {
      Color = engine.Vector.New(1, 1, 0)
    }
    PL.SetAnimatedMaterialAttributes(quiver, "feather", "base", lightMaterialParams)
    PL.SetAnimatedMaterialAttributes(quiver, "feather01", "base", lightMaterialParams)
    PL.SetAnimatedMaterialAttributes(quiver, "feather02", "base", lightMaterialParams)
  end
end
function InCombatInputLogic(ai, global, constants, inputType)
  for weaponInfo in ai:IterateActiveWeapons() do
    local gear = weaponInfo.Weapon
    if gear:GetName() == "quiver00" then
      quiver = gear
    end
  end
  if gVFSDebugAutonomousShoot.value == true and (inputType == "Tap" or inputType == "Charged" or inputType == "Regular") then
    if inputType == "Tap" then
      global.fireAtAllTargets = true
    end
    return
  end
  if global.usedSonInteractWhileOccupied then
    global.usedSonInteractWhileOccupied = false
    return
  end
  if inputType == "SwitchArrow" then
    if constants.lockArrowType == true then
      return
    end
    local cineNumber = game.Level.GetVariable("CompletedCineNumber")
    if 365 <= cineNumber and cineNumber < 390 then
      return
    end
    local arrowstage = ai:PickupGetStage("SonRuneArrow_Type")
    local hasLightArrow, hasShockArrow
    local lightResourceCount = game.Wallets.GetResourceValue("HERO", "ArrowUnlock_Light")
    if 1 <= lightResourceCount then
      hasLightArrow = true
    end
    local shockResourceCount = game.Wallets.GetResourceValue("HERO", "ArrowUnlock_Shock")
    if 1 <= shockResourceCount then
      hasShockArrow = true
    end
    if hasLightArrow and hasShockArrow then
      game.Audio.PlayBanterNonCritical("CBT_son_arrowswitch")
      if ai:PickupIsAcquired("SonArrow_Light") then
        ai:PickupAcquire("SonArrow_Shock")
        ai:PickupSetStage("SonRuneArrow_Type", 0)
      else
        ai:PickupAcquire("SonArrow_Light")
        ai:PickupSetStage("SonRuneArrow_Type", 1)
      end
    elseif hasShockArrow then
      if not ai:PickupIsAcquired("SonArrow_Shock") then
        ai:PickupAcquire("SonArrow_Shock")
      end
      ai:PickupSetStage("SonRuneArrow_Type", 0)
    elseif hasLightArrow then
      if not ai:PickupIsAcquired("SonArrow_Light") then
        ai:PickupAcquire("SonArrow_Light")
      end
      ai:PickupSetStage("SonRuneArrow_Type", 1)
    else
      if not ai:PickupIsAcquired("SonArrow_Regular") then
        ai:PickupAcquire("SonArrow_Regular")
      end
      ai:PickupSetStage("SonRuneArrow_Type", 2)
    end
    return
  end
  if ai:HasMarker("TweakPOIResOnly") or ai:HasMarker("TweakLogicOnly") then
    return
  end
  if ai:HasMarker("HeroInput") then
    global.heroInput = true
    ai:TriggerMoveEvent("kLESuper")
    return
  end
  if _G.gVFSDisableSonCommands.value == true then
    return
  end
  if not ai:HasMarker("AllowSyncShots") and ai:IsDoingSyncMove() then
    return
  end
  if ai:HasMarker("SonCommand_WorldInteraction") then
    return
  end
  if inputType == "Tap" then
    global.ChargedOrRegular = "none"
  end
  if ai:HasMarker("DisableCommandShot") then
    return
  end
  if DL.CheckCreatureContext(ai:GetContext(), "SON_COOLDOWN") and inputType == "Regular" then
    return
  end
  if global.bCommand_Action and global.actionTypeIndex ~= 1 then
    return
  end
  if game.Player.FindPlayer():IsInDebugMovementMode() then
    return
  end
  local noaction = false
  if inputType == "Regular" or ai:HasMarker("DisableSummon") then
    global.ChargedOrRegular = "Regular"
    global.actionTypeIndex = 2
  elseif inputType == "Charged" or inputType == "Charged_Jerk" then
    global.ChargedOrRegular = "Charged"
    global.actionTypeIndex = 3
  else
    noaction = true
  end
  if noaction then
    return
  end
  if global.emotionState.value == 3 and global.bInCombat then
    global.actionTypeIndex = 5
  end
  if inputType == "Charged_Jerk" then
    global.ChargedOrRegular = "Charged"
    global.actionTypeIndex = 3
  end
  local actionCost = constants.actionTypes[global.actionTypeIndex].cost
  local meterAmount = ai:MeterGetValue("Son_ArrowCount")
  if meterAmount >= constants.actionTypes[global.actionTypeIndex].cost or ai:HasMarker("AllowSyncShots") and ai:IsDoingSyncMove() or gVFSInfiniteMeter.value then
    global.combatstate_commandaction.Command_ActionPhase = 0
    global.bCommand_Action = true
  else
    game.Audio.PlayBanterNonCritical("cbt_son_out_of_meter")
  end
  return true
end
return profile.WrapLibrary({InputSetup = InputSetup})
