/*
 * ============================================================================
 *
 *  Zombie:Reloaded
 *
 *  File:          volumecontrol.inc
 *  Type:          Core
 *  Description:   Basic volume control for player to change.
 *
 *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

/**
 * Cookie names for client volume settings.
 */
#define ZVOLUME_COOKIE_ZSOUND "zr_zombie_volume"
#define ZVOLUME_COOKIE_AMBIENT "zr_ambient_volume"

/**
 * Cookie handles for client volume settings.
 */
new Handle:g_hZSoundVolumeCookie = INVALID_HANDLE;
new Handle:g_hAmbientVolumeCookie = INVALID_HANDLE;

/**
 * Per-client volume, as a fraction (0.0 - 1.0), applied on top of sounds
 * emitted through SEffectsEmitSoundFromClient() and SEffectsEmitAmbientSound().
 */
new Float:zfZSoundVolume[MAXPLAYERS + 1];
new Float:zfAmbientVolume[MAXPLAYERS + 1];

/**
 * Create commands specific to ZVolume.
 */
ZVolumeOnCommandsCreate()
{
    RegConsoleCmd("sm_zvol", Command_ZVolume, "Brings up the zvolume menu");
    RegConsoleCmd("sm_zvolume", Command_ZVolume, "Brings up the zvolume menu");
    RegConsoleCmd("sm_zsound", Command_ZSound, "Brings up the zsound menu");
    RegConsoleCmd("sm_zombie_volume", Command_ZSound, "Brings up the zsound menu");
    RegConsoleCmd("sm_zambient", Command_ZAmbient, "Brings up the ambient menu");
    RegConsoleCmd("sm_ambient_volume", Command_ZAmbient, "Brings up the ambient menu");
}

/**
 * Create ZVolume-related cookies here.
 */
ZVolumeOnCookiesCreate()
{
    if (g_hZSoundVolumeCookie == INVALID_HANDLE)
    {
        g_hZSoundVolumeCookie = RegClientCookie(ZVOLUME_COOKIE_ZSOUND, "Control Zombie Sound.", CookieAccess_Protected);
    }

    if (g_hAmbientVolumeCookie == INVALID_HANDLE)
    {
        g_hAmbientVolumeCookie = RegClientCookie(ZVOLUME_COOKIE_AMBIENT, "Control Ambient Sound.", CookieAccess_Protected);
    }
}

/**
 * Called once a client's saved cookies have been loaded from the database.
 *
 * @param client    The client index.
 */
ZVolumeOnCookiesCached(client)
{
    decl String:sValue[8];

    sValue[0] = '\0';
    GetClientCookie(client, g_hZSoundVolumeCookie, sValue, sizeof(sValue));
    if (!sValue[0])
    {
        new Float:seffectsvolume = GetConVarFloat(g_hCvarsList[CVAR_SEFFECTS_VOLUME]);
        IntToString(RoundToNearest(seffectsvolume * 100.0), sValue, sizeof(sValue));
    }
    SetZombieVoiceVolume(client, StringToInt(sValue));

    sValue[0] = '\0';
    GetClientCookie(client, g_hAmbientVolumeCookie, sValue, sizeof(sValue));
    if (!sValue[0])
    {
        new Float:ambientvolume = GetConVarFloat(g_hCvarsList[CVAR_AMBIENTSOUNDS_VOLUME]);
        IntToString(RoundToNearest(ambientvolume * 100.0), sValue, sizeof(sValue));
    }
    SetAmbientVolume(client, StringToInt(sValue));
}

/**
 * Returns the client's personal zombie-voice volume, as a fraction (0.0 - 1.0).
 *
 * @param client    The client index.
 */
Float:ZVolume_GetZSoundVolume(client)
{
    return zfZSoundVolume[client];
}

/**
 * Returns the client's personal ambient-sound volume, as a fraction (0.0 - 1.0).
 *
 * @param client    The client index.
 */
Float:ZVolume_GetAmbientVolume(client)
{
    return zfAmbientVolume[client];
}

/**
 * Command callback (sm_zvol, sm_zvolume)
 * Opens the volume control menu.
 */
public Action:Command_ZVolume(client, args)
{
    if (IsClientInGame(client))
    {
        VolumeControlMenu(client);
        return Plugin_Handled;
    }
    return Plugin_Handled;
}

VolumeControlMenu(client)
{
    new Handle:menu = CreateMenu(VolumeControlMenuHandler);

    decl String:sMenuTitle[128];
    Format(sMenuTitle, sizeof(sMenuTitle), "%t", "Volume_Menu_Title");
    SetMenuTitle(menu, sMenuTitle);

    decl String:sItem[64];

    Format(sItem, sizeof(sItem), "%t", "Zombie Voice");
    AddMenuItem(menu, "1", sItem);

    Format(sItem, sizeof(sItem), "%t", "Ambient");
    AddMenuItem(menu, "2", sItem);

    SetMenuExitBackButton(menu, true);
    DisplayMenu(menu, client, MENU_TIME_FOREVER);
}

public VolumeControlMenuHandler(Handle:menu, MenuAction:action, param1, param2)
{
    switch (action)
    {
        case MenuAction_Select:
        {
            decl String:info[32];
            GetMenuItem(menu, param2, info, sizeof(info));
            if (StrEqual(info, "1", false))
            {
                ZombieVoiceVolumeMenu(param1);
            }
            else if (StrEqual(info, "2"))
            {
                AmbientVolumeMenu(param1);
            }
        }
        case MenuAction_Cancel:
        {
            if (param2 == MenuCancel_ExitBack)
            {
                ZMenuMain(param1);
            }
        }
        case MenuAction_End:
        {
            CloseHandle(menu);
        }
    }
    return 0;
}

// Zombie Voice Section
/**
 * Command callback (sm_zsound, sm_zombie_volume)
 */
public Action:Command_ZSound(client, args)
{
    if (args == 0)
    {
        ZombieVoiceVolumeMenu(client);
        return Plugin_Handled;
    }

    decl String:sArg[32];
    GetCmdArg(1, sArg, sizeof(sArg));
    new iVolume = StringToInt(sArg);

    if (iVolume < 0 || iVolume > 100)
    {
        TranslationReplyToCommand(client, "ZombieVoice_Usage");
        return Plugin_Handled;
    }
    else if (0 <= iVolume <= 100)
    {
        SetZombieVoiceVolume(client, iVolume);
        return Plugin_Handled;
    }
    return Plugin_Handled;
}

ZombieVoiceVolumeMenu(client)
{
    new Handle:menu = CreateMenu(ZombieVoiceVolumeMenuHandler);

    decl String:sMenuTitle[128];
    Format(sMenuTitle, sizeof(sMenuTitle), "%t\n%t", "ZombieVoice_Title_Menu", RoundToNearest(zfZSoundVolume[client] * 100), "ZombieVoice_CommandUsage");
    SetMenuTitle(menu, sMenuTitle);

    AddMenuItem(menu, "1", "100%");
    AddMenuItem(menu, "2", "80%");
    AddMenuItem(menu, "3", "60%");
    AddMenuItem(menu, "4", "40%");
    AddMenuItem(menu, "5", "20%");

    SetMenuExitBackButton(menu, true);
    DisplayMenu(menu, client, MENU_TIME_FOREVER);
}

public ZombieVoiceVolumeMenuHandler(Handle:menu, MenuAction:action, param1, param2)
{
    switch (action)
    {
        case MenuAction_Select:
        {
            decl String:info[32];
            GetMenuItem(menu, param2, info, sizeof(info));
            if (StrEqual(info, "1", false))
            {
                SetZombieVoiceVolume(param1, 100);
                ZombieVoiceVolumeMenu(param1);
            }
            else if (StrEqual(info, "2"))
            {
                SetZombieVoiceVolume(param1, 80);
                ZombieVoiceVolumeMenu(param1);
            }
            else if (StrEqual(info, "3"))
            {
                SetZombieVoiceVolume(param1, 60);
                ZombieVoiceVolumeMenu(param1);
            }
            else if (StrEqual(info, "4"))
            {
                SetZombieVoiceVolume(param1, 40);
                ZombieVoiceVolumeMenu(param1);
            }
            else if (StrEqual(info, "5"))
            {
                SetZombieVoiceVolume(param1, 20);
                ZombieVoiceVolumeMenu(param1);
            }
        }
        case MenuAction_Cancel:
        {
            if (param2 == MenuCancel_ExitBack)
            {
                VolumeControlMenu(param1);
            }
        }
        case MenuAction_End:
        {
            CloseHandle(menu);
        }
    }
    return 0;
}

SetZombieVoiceVolume(client, volume)
{
    zfZSoundVolume[client] = volume * 0.01;

    decl String:sValue[8];
    IntToString(volume, sValue, sizeof(sValue));
    SetClientCookie(client, g_hZSoundVolumeCookie, sValue);

    if (IsClientInGame(client))
    {
        TranslationPrintToChat(client, "Set_ZombieVoice_Volume", volume);
    }
}

// Ambient Section
/**
 * Command callback (sm_zambient, sm_ambient_volume)
 */
public Action:Command_ZAmbient(client, args)
{
    if (args == 0)
    {
        AmbientVolumeMenu(client);
        return Plugin_Handled;
    }

    decl String:sArg[32];
    GetCmdArg(1, sArg, sizeof(sArg));
    new iVolume = StringToInt(sArg);

    if (iVolume < 0 || iVolume > 100)
    {
        TranslationReplyToCommand(client, "Ambient_Usage");
        return Plugin_Handled;
    }
    else if (0 <= iVolume <= 100)
    {
        SetAmbientVolume(client, iVolume);
        return Plugin_Handled;
    }
    return Plugin_Handled;
}

AmbientVolumeMenu(client)
{
    new Handle:menu = CreateMenu(AmbientVolumeMenuHandler);

    decl String:sMenuTitle[128];
    Format(sMenuTitle, sizeof(sMenuTitle), "%t\n%t", "Ambient_Title_Menu", RoundToNearest(zfAmbientVolume[client] * 100), "Ambient_CommandUsage");
    SetMenuTitle(menu, sMenuTitle);

    AddMenuItem(menu, "1", "100%");
    AddMenuItem(menu, "2", "80%");
    AddMenuItem(menu, "3", "60%");
    AddMenuItem(menu, "4", "40%");
    AddMenuItem(menu, "5", "20%");

    SetMenuExitBackButton(menu, true);
    DisplayMenu(menu, client, MENU_TIME_FOREVER);
}

public AmbientVolumeMenuHandler(Handle:menu, MenuAction:action, param1, param2)
{
    switch (action)
    {
        case MenuAction_Select:
        {
            decl String:info[32];
            GetMenuItem(menu, param2, info, sizeof(info));
            if (StrEqual(info, "1", false))
            {
                SetAmbientVolume(param1, 100);
                AmbientVolumeMenu(param1);
            }
            else if (StrEqual(info, "2"))
            {
                SetAmbientVolume(param1, 80);
                AmbientVolumeMenu(param1);
            }
            else if (StrEqual(info, "3"))
            {
                SetAmbientVolume(param1, 60);
                AmbientVolumeMenu(param1);
            }
            else if (StrEqual(info, "4"))
            {
                SetAmbientVolume(param1, 40);
                AmbientVolumeMenu(param1);
            }
            else if (StrEqual(info, "5"))
            {
                SetAmbientVolume(param1, 20);
                AmbientVolumeMenu(param1);
            }
        }
        case MenuAction_Cancel:
        {
            if (param2 == MenuCancel_ExitBack)
            {
                VolumeControlMenu(param1);
            }
        }
        case MenuAction_End:
        {
            CloseHandle(menu);
        }
    }
    return 0;
}

SetAmbientVolume(client, volume)
{
    zfAmbientVolume[client] = volume * 0.01;

    decl String:sValue[8];
    IntToString(volume, sValue, sizeof(sValue));
    SetClientCookie(client, g_hAmbientVolumeCookie, sValue);

    if (IsClientInGame(client))
    {
        TranslationPrintToChat(client, "Set_Ambient_Volume", volume);
    }
}
