MusicState = inherited("MusicState", State)

function MusicState:new()
	local ms = instance(self)
	ms.channels = {} 
	ms:addChannel("main")
	return ms
end

function MusicState:addChannel(id)
	local channel = {currentMusic = "",
					nextMusic = nil,
					fadeProgress = 0,
					fadeOut = false,
					fadeOutTime = 2, 
					fadeInTime = 0.5,
					looping = true,
					volume = 1,
					volumeTarget = 1,
					
					}
	self.channels[id] = channel
end

function MusicState:getChannel(id)
	if not self.channels[id] then
		self:addChannel(id)
	end
	return self.channels[id]
end

function MusicState:setIntro(intro, introtime, introfadetime, channel)
	local channel = self:getChannel(channel or "main")
	channel.nextIntro = intro
	channel.introtime = introtime or 5
	channel.introtimer = 0
	channel.introfadetime =introfadetime or 1
	channel.introMusic = nil
end
	
function MusicState:setNextMusic(file, fadetime, looping, channel)
	local channel = self:getChannel(channel or "main")
	
	if file ~= channel.currentMusic then
		channel.nextMusic = file
		channel.fadeOutTime = fadetime
		channel.fadeInTime = 0.5
		if looping ~= nil then
			channel.looping = looping
		else
			channel.looping = true
		end
	end	
end

local musicPath = "music/"

function MusicState:stopCurrentMusic(channel)
	local channel = self:getChannel(channel or "main")
	if channel.currentMusic then
		audio.stopMusic(musicPath..channel.currentMusic)
		channel.currentMusic = ""
	end
	if channel.introMusic then
		audio.stopMusic(musicPath..channel.introMusic)
		channel.introMusic = nil
	end
	channel.nextIntro = nil
	channel.nextMusic = nil
	self.channels[channel or "main"] = nil
end

function MusicState:fadeOutMusic(duration, channel)
	local channel = self:getChannel(channel or "main")
	channel.fadeOutTime = duration
	channel.fadeOut = true
end

function MusicState:forceMusicVolume(vol, channel)
	local channel = self:getChannel(channel or "main")
	channel.volumeTarget = vol
end

function MusicState:close()
	self.channels = {}
	audio.stopAllMusic()
end

			
function MusicState:update(time)
	if DEBUG.disableSounds then
		audio.stopAllMusic()
		return
	end
	if _config.musicVolume <= 0 then
		if self.anyMusic then
			audio.stopAllMusic()
			self.anyMusic = false
		end
		return
	end
	
	for channelIndex, channel in pairs(self.channels) do
		local hold = false
		local skipFade = false
		if channel.nextIntro then
			channel.introtimer = channel.introtimer + time
			if not channel.introMusic then
				channel.introMusic = channel.nextIntro
				audio.playMusic(musicPath..channel.nextIntro, _config.musicVolume*channel.volume, false)
				hold = true
				self.anyMusic = true
			else
				if channel.introtimer < channel.introtime then
					hold = true
					audio.updateMusic(musicPath..channel.introMusic, _config.musicVolume*channel.volume )
				else
					
					local fade = math.max(0,(channel.introfadetime - (channel.introtimer-channel.introtime))/channel.introfadetime)
					if channel.introfadetime > 0 and fade > 0 then
						audio.updateMusic(musicPath..channel.introMusic, fade*_config.musicVolume*channel.volume )
						channel.fadeInTime = channel.introfadetime
					else
						skipFade = true
						audio.stopMusic(musicPath..channel.introMusic)
						channel.introMusic = nil
						channel.nextIntro = nil
					end
				end
			end
		end

		if not hold then
			if channel.nextMusic then
				channel.fadeOut = false
				if channel.currentMusic ~= "" then
					channel.fadeProgress = math.max(0,channel.fadeProgress - time / channel.fadeOutTime)
					audio.updateMusic(musicPath..channel.currentMusic, channel.fadeProgress*_config.musicVolume*channel.volume )
					if channel.fadeProgress <= 0 then
						audio.stopMusic(musicPath..channel.currentMusic)
						channel.currentMusic = channel.nextMusic
						audio.playMusic(musicPath..channel.currentMusic, 0, channel.looping)
						self.anyMusic = true
						channel.nextMusic = nil
					end
				else
					channel.currentMusic = channel.nextMusic
					if not skipFade then
						channel.fadeProgress = 0
					else
						channel.fadeProgress = 1
					end
					
					audio.playMusic(musicPath..channel.currentMusic, channel.fadeProgress*_config.musicVolume*channel.volume, channel.looping)
					self.anyMusic = true
					channel.nextMusic = nil
				end
			else
				if channel.fadeProgress <= 1.0 and not channel.fadeOut then
					channel.fadeProgress = math.min(1,channel.fadeProgress + time / channel.fadeInTime)
					audio.updateMusic(musicPath..channel.currentMusic, channel.fadeProgress*_config.musicVolume*channel.volume )
				elseif channel.fadeProgress > 0 and channel.fadeOut then
					channel.fadeProgress = math.max(0,channel.fadeProgress - time / channel.fadeOutTime)
					audio.updateMusic(musicPath..channel.currentMusic, channel.fadeProgress*_config.musicVolume*channel.volume )
					if channel.fadeProgress <= 0 then
						audio.stopMusic(musicPath..channel.currentMusic)
						channel.currentMusic = ""
						channel.fadeOut = false
						self.channels[channelIndex] = nil
					end
				elseif channel.volume < 1 and channel.currentMusic ~= "" then
					audio.updateMusic(musicPath..channel.currentMusic, channel.fadeProgress*_config.musicVolume*channel.volume )
				end
			end
		end
		if daisy.isWindowInFocus then
			if not daisy.isWindowInFocus() and _config.muteWhenOutOfFocus then
				channel.volumeTarget = 0
				channel.volume = 0
			end
		end
		if channel.volumeTarget > channel.volume then
			channel.volume = math.min(channel.volumeTarget,channel.volume + (channel.volumeTarget-channel.volume)*time*2)
		else
			channel.volume = math.max(channel.volumeTarget,channel.volume + (channel.volumeTarget-channel.volume)*time*2)
		end
		channel.volumeTarget = 1
	end
end