local dfpwm = require("cc.audio.dfpwm")

---@alias AudioControllerConfig {buffer_length_seconds: number}

---@class AudioController
---@field config AudioControllerConfig
---@field play boolean
local AudioController = {}
AudioController.__index = AudioController

---@return AudioController
function AudioController:Create()
	local t = {}
	setmetatable(t, AudioController)

	-----------------------------------------------------------------------------------------------
	-- Fields
	-----------------------------------------------------------------------------------------------
	t.config = {
		buffer_length_seconds = 1,
	}
	t.play = false

	return t
end

-----------------------------------------------------------------------------------------------
-- Audio Methods
-----------------------------------------------------------------------------------------------

function AudioController:PlayAudio(filename)
	self.play = true

	local decoder = dfpwm.make_decoder()
	while self.play do
		for chunk in io.lines(("audio/%s.dfpwm"):format(filename), self.config.buffer_length_seconds * 1024) do
			if not self.play then
				break
			end

			local buffer = decoder(chunk)

			while not self:GetSpeaker().playAudio(buffer) do
				if not self.play then
					break
				end

				---@diagnostic disable-next-line: undefined-field
				os.pullEvent("speaker_audio_empty")
			end
		end
	end
end

function AudioController:PlayAudioFactory(filename)
	local function play()
		self:PlayAudio(filename)
	end

	return play
end

-----------------------------------------------------------------------------------------------
-- Management Methods
-----------------------------------------------------------------------------------------------

---@return table | nil
function AudioController:GetSpeaker()
	return peripheral.find("speaker")
end

function AudioController:StopPlaying()
	self.play = false
	self:GetSpeaker().stop()
end

-----------------------------------------------------------------------------------------------
-- Main Method
-----------------------------------------------------------------------------------------------

function AudioController:Run()
	-- self:Configure()

	self:PlayAudio("bangarang")
end

return AudioController
