-- Class Functions

function Animater:Play(name: string, options: options)
	options = (options and (type(options == "table"))) and options or {}
	
	if self.Tracks[name] then
		-- TODO: Add indexability to list of tracks for one animation name.
		local track: AnimationTrack = self.Tracks[name][1]
		
		if track then
			if options.stopOthers then
				for _, trackList in next, self.Tracks do
					for _, t in next, trackList do
						if t.IsPlaying and t ~= track then
							t:Stop(options.fadeOut or self.FadeOut)
						end
					end
				end
			end
			
			if options.forceStart or not track.IsPlaying then
				track:Play(options.fadeIn or self.FadeIn, options.weight or 1, options.speed or 1)
			end 
		end
	end
end

function Animater:Stop(name: string, options: options?)
	options = (options and (type(options == "table"))) and options or {}

	if self.Tracks[name] then
		-- TODO: Add indexability to list of tracks for one animation name.
		local track: AnimationTrack = self.Tracks[name][1]
		
		track:Stop(options.fadeOut or self.FadeOut)
	end
end

function Animater:Get(name: string, pos: number?) : AnimationTrack?
	if self.Tracks[name] then
		if pos and self.Tracks[name][pos] then
			return self.Tracks[name][pos]
		else
			return self.Tracks[name][math.random(1, #self.Tracks[name])]
		end
	end
	return nil
end

function Animater:Has(name: string, pos: number?) : boolean
	if self.Tracks[name] then
		if pos and self.Tracks[name][pos] then
			return true
		elseif self.Tracks[name][math.random(1, #self.Tracks[name])] then
			return true
		end
	end
	return false
end

function Animater:SetSpeed(name: string, speed: number, pos: number?)
	if self.Tracks[name] then
		local track: AnimationTrack = self.Tracks[name][pos or math.random( 1, #self.Tracks[name] )]

		if track then
			track:AdjustSpeed(speed)
		end
	end
end

function Animater:LoadAnimation(name: string, animation: Animation, options: AnimationIndex)
	local track: AnimationTrack = self.Controller:LoadAnimation(animation)
	
	self._maid:GiveTask(track)
	track.Priority = self.Priority or Enum.AnimationPriority.Core
	track:AdjustSpeed(options.speed or 1)
	track:AdjustWeight(options.weight or 1, options.weightFade or 0.100000001)

	self.Tracks[name][1] = track
end

function Animater:LoadAnimationIndex(name: string, animationIndex: AnimationIndex)
	local animation: Animation = Instance.new('Animation')
	
	self._maid:GiveTask(animation)
	animation.AnimationId = animationIndex.id
	animation.Name = name
	
	self:LoadAnimation(name, animation, animationIndex)
end

function Animater:LoadAnimationTable(animationTable: { [string]: AnimationIndex })
	for name, sublist in next, animationTable do
		self.Tracks[name] = {}
		if sublist.id then
			self:LoadAnimationIndex(name, sublist)
		else
			-- TODO: Add multiple entries for one animation name
		end
	end
end

function Animater:SetController(controller: Controller)
	self:Clean()
	self.Controller = controller
end

function Animater:SetPriority(priority: Enum.AnimationPriority)
	self.Priority = priority
end

function Animater:Clean()
	for _, sublist in next, self.Tracks do
		for _, track: AnimationTrack in next, sublist do
			track:Stop(0)
		end
	end
	self._maid:DoCleaning()
	self.Tracks = {}
end

function Animater:Destroy()
	self:Clean()
	table.clear(self)
	self = nil
end

return Animater