require "behaviours/follow"
require "behaviours/panic"
require "behaviours/standstill"
require "behaviours/chaseandattack"
require "behaviours/leash"
require "behaviours/wander"
require "behaviours/faceentity"
require "behaviours/runaway"
require "behaviours/doaction"
require "behaviours/findlight"
require "behaviours/chattynode"

local MIN_FOLLOW_DIST = 2
local MAX_FOLLOW_DIST = 6
local TARGET_FOLLOW_DIST = (MAX_FOLLOW_DIST+MIN_FOLLOW_DIST)*2
local MIN_FOLLOW_LEADER = 1
local MAX_FOLLOW_LEADER = 6
local TARGET_FOLLOW_LEADER = 2
local MAX_CHASE_TIME = 30
local MAX_CHASE_DIST = 30
local TRADE_DIST = 20
local SEE_FOOD_DIST = 15
local MAX_WANDER_DIST = 20
local START_RUN_DIST = 4
local STOP_RUN_DIST = 6
local RUN_AWAY_DIST = 4
local STOP_RUN_AWAY_DIST = 6
local GO_HOME_DIST = 0

local function GetFaceTargetFn(inst)
    return inst.components.follower.leader
end

local function KeepFaceTargetFn(inst, target)
    return inst.components.follower.leader == target
end

local function GetLeader(inst)
   return inst.components.follower and inst.components.follower.leader
end

local function GetStayPos(inst)
	return inst.components.petstay.locations["stayspos"]
end

local function ShouldGoHome(inst)
    local homePos = inst.components.petstay.locations["stayspos"]
    local myPos = Vector3(inst.Transform:GetWorldPosition() )
    return (homePos and distsq(homePos, myPos) > GO_HOME_DIST)
end

local function GoHomeAction(inst)
    local homePos = inst.components.petstay.locations["stayspos"]
    if homePos then
        return BufferedAction(inst, nil, ACTIONS.GOHOME, nil, homePos, nil, 1)
    end
end

local function GetWanderPoint(inst)
	if inst.components.petstay and inst.components.petstay:IsCurrentlyStaying() then
		return GetStayPos(inst)
	else
		local target = GetLeader(inst) or GetPlayer()
   		if target then
        		return target:GetPosition()
    		end
	end
end

local function GetTraderFn(inst)
    return (inst.components.follower.leader and inst.components.trader:IsTryingToTradeWithMe(inst.components.follower.leader)) and inst.components.follower.leader or nil
end

local function KeepTraderFn(inst, target)
    return inst.components.trader:IsTryingToTradeWithMe(target)
end

local function ShouldRunAwayFromPlayer(inst, player)
    return not inst.components.follower.leader
end

local function ShouldStandStill(inst)
    return
end

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

function MirBrain:OnStart()
    local root = 
    PriorityNode({
	ChattyNode(self.inst, STRINGS.MIR_TALK_FIGHT,
	WhileNode( function() return self.inst.components.combat.target == nil or not self.inst.components.combat:InCooldown() end, "AttackMomentarily",
	ChaseAndAttack(self.inst, MAX_CHASE_TIME, MAX_CHASE_DIST) )),
	WhileNode( function() return self.inst.components.combat.target and self.inst.components.combat:InCooldown() end, "Dodge",
	RunAway(self.inst, function() return self.inst.components.combat.target end, RUN_AWAY_DIST, STOP_RUN_AWAY_DIST) ),
	RunAway(self.inst, "player", START_RUN_DIST, STOP_RUN_DIST, function(target) return ShouldRunAwayFromPlayer(self.inst, target) end ),
	IfNode(function() 
		if self.inst.components.follower.leader ~= nil and self.inst.components.petstay and self.inst.components.petstay:IsCurrentlyStaying() == false then
		return true
		elseif self.inst.components.follower.leader ~= nil and not self.inst.components.petstay then
		return true
		end
		end, "has leader",	
		Follow(self.inst, GetLeader, MIN_FOLLOW_LEADER, TARGET_FOLLOW_LEADER, MAX_FOLLOW_LEADER)),
	IfNode(function()
		if self.inst.components.follower.leader ~= nil and self.inst.components.petstay and self.inst.components.petstay:IsCurrentlyStaying() == true then
		return true
		end
		end, "has leader",
		WhileNode(function() return ShouldGoHome(self.inst) end, "ShouldGoHome",
		DoAction(self.inst, GoHomeAction, "Go Home", true ))),  
		
	IfNode(function() return self.inst.components.follower.leader ~= nil end, "has leader",
		FaceEntity(self.inst, GetFaceTargetFn, KeepFaceTargetFn )),
	PriorityNode {
        StandStill(self.inst, ShouldStandStill),
        Follow(self.inst, function() return self.inst.components.follower.leader end, MIN_FOLLOW_DIST, TARGET_FOLLOW_DIST, MAX_FOLLOW_DIST),
        },
	--Wander(self.inst, function() if self.inst.components.follower.leader then return Vector3(self.inst.components.follower.leader.Transform:GetWorldPosition()) end end, MAX_FOLLOW_DIST- 1, {minwalktime=.5, randwalktime=.5, minwaittime=6, randwaittime=3}),
}, .5)
self.bt = BT(self.inst, root)
end

return MirBrain