--------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------- [[ Music and Sound module ]] -----------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------
-- Functions related to music and sounds.

-- Ambient sound type:
ffi.cdef[[
    typedef struct CAmbientSound {
        const void* _vtable;
        const void* _buffer;
        int mainVolume;
        int appSoundsManagerVolume;
        int volume;
        bool isPlaying;
        Rect rect;
        Rect rect2;
        int field_38;
        const void *_listNode;
    } CAmbientSound;
]]

local MUS = {
    SwapedSoundAssets = {}
}

MUS.RestoreSoundAssets = function()
    for name, ptr in pairs(MUS.SwapedSoundAssets) do
        local sound = mdl_exe._GetSound(Game(10)+16, name)
        if sound ~= nil then
            sound[0] = ptr
        end
    end
end

MUS.GetMusicState = function(name)
    name = type(name) == "string" and string.upper(name) or ""
    local tracks = GetMusicTracks()
    if table.icontain(tracks, name) then
        local ptr = mdl_exe._GetMusic(nRes(20), name)
        return mdl_exe._GetMusicState(ptr) ~= 0
    else
        return false
    end
end

MUS.StopMusic = function(name)
	name = string.upper(name)
    local music_plays = MUS.GetMusicState(name)
	if music_plays then
	    local ptr = mdl_exe._GetMusic(nRes(20), name)
        mdl_exe._StopMusic(ptr)
    end
end

MUS.SetMusicSpeed = function(name, speed)
    name = string.upper(name)
    local music_plays = MUS.GetMusicState(name)
    if music_plays then
        mdl_exe._SetMusicSpeed(nRes(20,7), name, speed < 0 and 0 or math.floor(speed*1000))
    end
end

MUS.SetMusicVolume = function(vol)
	vol = vol > 100 and 100 or vol < 0 and 0 or vol
	mdl_exe._SetMusicVolume(vol)
end

MUS.PlaySound = function(name, volume, stereo, pitch, loop)
	local sound = mdl_exe._GetSoundA(Game(10), name)
    if sound == nil then return end
	if not volume or volume == 1 then
		volume = mdl_exe.SoundVolume[0]
	elseif volume >= 3 then
		volume = 3*mdl_exe.SoundVolume[0]
	elseif volume <= 0 then
		volume = 0
	else
		volume = volume*mdl_exe.SoundVolume[0]
	end
	mdl_exe._PlaySound(sound, volume, stereo or 0, pitch or 0, loop or 0)
end

MUS.ReplaceSound = function(name1, name2)
    local sound1 = mdl_exe._GetSound(Game(10)+16, name1)
    if sound1 == nil then return false end
	local sound2 = mdl_exe._GetSound(Game(10)+16, name2)
    if sound2 == nil then return false end
    MUS.SwapedSoundAssets[name1] = sound1[0]
	sound1[0] = sound2[0]
    return true
end

MUS.SwapSound = function(name1, name2)
    local sound1 = mdl_exe._GetSound(Game(10)+16, name1)
    if sound1 == nil then return false end
	local sound2 = mdl_exe._GetSound(Game(10)+16, name2)
    if sound2 == nil then return false end
    MUS.SwapedSoundAssets[name1] = sound1[0]
    MUS.SwapedSoundAssets[name2] = sound2[0]
    local temp = sound1[0]
	sound1[0] = sound2[0]
    sound2[0] = temp
    return true
end

MUS.RemoveSound = function(name)
    local sound1 = mdl_exe._GetSound(Game(10)+16, name)
    if sound1 == nil then return false end
	local sound2 = mdl_exe._GetSound(Game(10)+16, "GAME_NULL")
    if sound2 == nil then return false end
    MUS.SwapedSoundAssets[name] = sound1[0]
	sound1[0] = sound2[0]
    return true
end

MUS.RestoreSound = function(name)
    if not MUS.SwapedSoundAssets[name] then return false end
    local sound = mdl_exe._GetSound(Game(10)+16, name)
    if sound == nil then return false end
    sound[0] = MUS.SwapedSoundAssets[name]
    MUS.SwapedSoundAssets[name] = nil
    return true
end

MUS.StopSound = function(name)
	local sound = mdl_exe._GetSoundA(Game(10), name)
    if sound ~= nil then
		mdl_exe._StopSound(sound[4])
	end
end

MUS.EnemySound = function(object, name)
    local sound = mdl_exe._GetSoundA(Game(10), name)
    if sound ~= nil then
        mdl_exe._EnemySound(object, sound, 0)
    end
end

return MUS