require "behaviours/standstill"
require "behaviours/runaway"
require "behaviours/doaction"
require "behaviours/panic"
require "behaviours/wander"

local START_FACE_DIST = 5
local KEEP_FACE_DIST = 7

local STOP_RUN_DIST = 7
local SEE_PLAYER_DIST = 5
local SEE_FOOD_DIST = 10

local MAX_WANDER_DIST = 30
local NO_TAGS = { "FX", "NOCLICK", "DECOR", "INLIMBO" }

local MIN_FOLLOW_DIST = 5
local TARGET_FOLLOW_DIST = 6.5
local MAX_FOLLOW_DIST = 8

local FruitbatBrain = Class(Brain, function(self, inst)
    Brain._ctor(self, inst)
end)

local function GetFaceTargetFn(inst)
	local target = FindClosestPlayerToInst(inst, START_FACE_DIST, true)
	return target ~= nil and not target:HasTag("notarget") and target or nil
end

local function KeepFaceTargetFn(inst, target)
	return not target:HasTag("notarget") and inst:IsNear(target, KEEP_FACE_DIST)
end

local function GoHomeAction(inst)
    return inst.components.homeseeker ~= nil
        and inst.components.homeseeker.home ~= nil
        and inst.components.homeseeker.home:IsValid()
        and inst.components.homeseeker.home.components.childspawner ~= nil
        and BufferedAction(inst, inst.components.homeseeker.home, ACTIONS.GOHOME)
        or nil
end

local function EatFoodAction(inst)
    if inst.sg:HasStateTag("busy") then
        return
    elseif inst.components.inventory ~= nil and inst.components.eater ~= nil then
        local target = inst.components.inventory:FindItem(function(item)
            return inst.components.eater:CanEat(item)
        end)
        if target ~= nil then
            return BufferedAction(inst, target, ACTIONS.EAT)
        end
    end

    local target = FindEntity(
        inst,
        SEE_FOOD_DIST,
        function(item)
            return item:GetTimeAlive() >= 8
                and item:IsOnValidGround()
                and inst.components.eater:CanEat(item)
        end,
        nil,
        NO_TAGS,
        inst.components.eater:GetEdibleTags()
    )
    return target ~= nil and BufferedAction(inst, target, ACTIONS.PICKUP) or nil
end

local function ScaredLoseLoyalty(self)
    local t = GetTime()
    if t >= self.scareendtime then
        self.scaredelay = nil
    elseif self.scaredelay == nil then
        self.scaredelay = t + 3
    elseif t >= self.scaredelay then
        self.scaredelay = t + 3
        if math.random() < .2 and
            self.inst.components.follower ~= nil and
            self.inst.components.follower:GetLoyaltyPercent() > 0 and
            self.inst.components.follower:GetLeader() ~= nil then
            self.inst.components.follower:SetLeader(nil)
            if self.inst.components.combat ~= nil then
                self.inst.components.combat:SetTarget(nil)
            end
        end
    end
end

function FruitbatBrain:OnStart()
    local root = PriorityNode({
        EventNode(self.inst, "panic",
            ParallelNode{
				LoopNode{
                ActionNode(function() ScaredLoseLoyalty(self) end),
            },
                Panic(self.inst),
                WaitNode(6),
            }),
        WhileNode(function() return self.inst.components.health.takingfiredamage or self.inst.components.hauntable.panic end, "Panic", Panic(self.inst)),
        WhileNode(function() return TheWorld.state.isday end, "IsDay",
		RunAway(self.inst, "scarytoprey", SEE_PLAYER_DIST, STOP_RUN_DIST),
            DoAction(self.inst, GoHomeAction)),
        PriorityNode{
				Follow(self.inst, function(inst) return inst.components.follower.leader end, MIN_FOLLOW_DIST, TARGET_FOLLOW_DIST, MAX_FOLLOW_DIST),
				FaceEntity(self.inst, GetFaceTargetFn, KeepFaceTargetFn),
                DoAction(self.inst, EatFoodAction),
                Wander(self.inst, function() return self.inst.components.knownlocations:GetLocation("home") end, MAX_WANDER_DIST),
            },
    }, .25)

    self.bt = BT(self.inst, root)
end

function FruitbatBrain:OnInitializationComplete()
    self.inst.components.knownlocations:RememberLocation("home", self.inst:GetPosition(), true)
end

return FruitbatBrain
