--! Previous: sha1:c549ad6cc4dc88d928043916e2696eeed3efa420
--! Hash: sha1:defb8b93ce936f1bb553abb90aaa6ecd5a00b1bc
--! Message: Fix some more procedures

--- Gets whether the users may use game commands in the current channel/guild.
--- Error codes:
---     VGBCG: Bad channel (game). This is not a valid channel to send game commands in.
---     VGBGG: Bad guild (game). This is not a valid guild to send game commands in.
CREATE OR REPLACE PROCEDURE CheckGameCommandIn(
    IN requestedChannel DiscordChannel.DiscordId%TYPE,
    IN requestedGuild DiscordChannel.GuildId%TYPE)
AS
$$
DECLARE
    channelAcceptsGameCommands  BOOLEAN;
    channelAcceptsAdminCommands BOOLEAN;
    channelSendsMessages        BOOLEAN;
    channelIsKnown              BOOLEAN;
    guildSupportsGameCommands   BOOLEAN;
    guildSupportsAdminCommands  BOOLEAN;
    guildSupportsMessages       BOOLEAN;
    guildIsKnown                BOOLEAN;
    recommendedChannelId        DiscordChannel.DiscordId%TYPE;
BEGIN
    SELECT acceptGameCommands, acceptAdminCommands, broadcastGame OR sendLogs, TRUE
    INTO channelAcceptsGameCommands, channelAcceptsAdminCommands, channelSendsMessages, channelIsKnown
    FROM DiscordChannel
    WHERE discordId = requestedChannel
    LIMIT 1;
    IF channelAcceptsGameCommands IS NOT TRUE THEN
        SELECT discordId, acceptGameCommands, acceptAdminCommands, broadcastGame OR sendLogs, TRUE
        INTO recommendedChannelId, guildSupportsGameCommands, guildSupportsAdminCommands, guildSupportsMessages, guildIsKnown
        FROM DiscordChannel
        WHERE guildId = requestedGuild
        ORDER BY CASE TRUE
                     WHEN acceptGameCommands THEN 3
                     WHEN acceptAdminCommands THEN 2
                     WHEN broadcastGame OR sendLogs THEN 1
                     ELSE 0
                     END DESC, priority DESC
        LIMIT 1;
        IF guildSupportsGameCommands IS TRUE THEN
            RAISE EXCEPTION 'Can''t use game commands in this channel' USING
                ERRCODE = 'VGBCG',
                DETAIL = CASE TRUE
                             WHEN channelAcceptsGameCommands THEN format(
                                     'This channel (<#%s>) can only be used to send admin commands, not game commands.',
                                     requestedChannel)
                             WHEN channelSendsMessages THEN format(
                                     'This channel (<#%s>) is only used to receive broadcasts, not send commands.',
                                     requestedChannel)
                             WHEN channelIsKnown THEN format(
                                     'This channel (<#%s>) is unused.', requestedChannel)
                             ELSE format('This channel (<#%s>) is not known to the system.', requestedChannel)
                    END,
                HINT = format(
                        'Try sending messages to the channel <#%s> in this guild, which does allow game commands.',
                        recommendedChannelId);
        ELSE
            RAISE EXCEPTION 'Can''t use game commands in this guild' USING
                ERRCODE = 'VGBGG',
                DETAIL = CASE TRUE
                             WHEN guildSupportsAdminCommands THEN
                                 format('This guild (ID %) only has channels used to send admin commands, ' ||
                                        'not game commands.', requestedGuild)
                             WHEN guildSupportsMessages THEN
                                 format('This guild (ID %) only has channels used to receive broadcasts, ' ||
                                        'not send commands.', requestedGuild)
                             WHEN guildIsKnown THEN
                                 format('This guild (ID %) only has unused channels.', requestedGuild)
                             ELSE format('This guild (ID %) is not known to the system.', requestedGuild)
                    END,
                HINT = 'As game commands are normally only visible when a guild allows them, ' ||
                       'this guild may have been removed from the system incorrectly. ' ||
                       'Ask an admin to check what''s going on.';
        END IF;
    END IF;
END;
$$ LANGUAGE 'plpgsql';

--- Gets whether the users may use admin commands in the current channel/guild.
--- Error codes:
---     VGBCA: Bad channel (admin). This is not a valid channel to send admin commands in.
---     VGBGA: Bad guild (admin). This is not a valid guild to send admin commands in.
CREATE OR REPLACE PROCEDURE CheckAdminCommandIn(
    IN requestedChannel DiscordChannel.DiscordId%TYPE,
    IN requestedGuild DiscordChannel.GuildId%TYPE)
AS
$$
DECLARE
    channelAcceptsAdminCommands BOOLEAN;
    channelAcceptsGameCommands  BOOLEAN;
    channelSendsMessages        BOOLEAN;
    channelIsKnown              BOOLEAN;
    guildSupportsAdminCommands  BOOLEAN;
    guildSupportsGameCommands   BOOLEAN;
    guildSupportsMessages       BOOLEAN;
    guildIsKnown                BOOLEAN;
    recommendedChannelId        DiscordChannel.DiscordId%TYPE;
BEGIN
    SELECT acceptAdminCommands, acceptGameCommands, broadcastGame OR sendLogs, TRUE
    INTO channelAcceptsAdminCommands, channelAcceptsGameCommands, channelSendsMessages, channelIsKnown
    FROM DiscordChannel
    WHERE discordId = requestedChannel
    LIMIT 1;
    IF channelAcceptsAdminCommands IS NOT TRUE THEN
        SELECT discordId, acceptAdminCommands, acceptGameCommands, broadcastGame OR sendLogs, TRUE
        INTO recommendedChannelId, guildSupportsAdminCommands, guildSupportsGameCommands, guildSupportsMessages, guildIsKnown
        FROM DiscordChannel
        WHERE guildId = requestedGuild
        ORDER BY CASE TRUE
                     WHEN acceptAdminCommands THEN 3
                     WHEN acceptGameCommands THEN 2
                     WHEN broadcastGame OR sendLogs THEN 1
                     ELSE 0
                     END DESC, priority DESC
        LIMIT 1;
        IF guildSupportsAdminCommands IS TRUE THEN
            RAISE EXCEPTION 'Can''t use admin commands in this channel' USING
                ERRCODE = 'VGBCA',
                DETAIL = CASE TRUE
                             WHEN channelAcceptsGameCommands THEN format(
                                     'This channel (<#%s>) can only be used to send admin commands, not game commands.',
                                     requestedChannel)
                             WHEN channelSendsMessages THEN format(
                                     'This channel (<#%s>) is only used to receive broadcasts, not send commands.',
                                     requestedChannel)
                             WHEN channelIsKnown THEN format(
                                     'This channel (<#%s>) is unused.', requestedChannel)
                             ELSE format('This channel (<#%s>) is not known to the system.', requestedChannel)
                    END,
                HINT = format(
                        'Try sending messages to the channel <#%s> in this guild, which does allow game commands.',
                        recommendedChannelId);
        ELSE
            RAISE EXCEPTION 'Can''t use admin commands in this guild' USING
                ERRCODE = 'VGBGA',
                DETAIL = CASE TRUE
                             WHEN guildSupportsGameCommands THEN
                                 format('This guild (ID %s) only has channels used to send game commands, ' ||
                                        'not admin commands.', requestedGuild)
                             WHEN guildSupportsMessages THEN
                                 format('This guild (ID %s) only has channels used to receive broadcasts, ' ||
                                        'not send commands.', requestedGuild)
                             WHEN guildIsKnown THEN
                                 format('This guild (ID %s) only has unused channels.', requestedGuild)
                             ELSE format('This guild (ID %s) is not known to the system.', requestedGuild)
                    END,
                HINT = 'As admin commands are normally only visible when a guild allows them, ' ||
                       'this guild may have been removed from the system incorrectly. ' ||
                       'Ask an admin to check what''s going on.';
        END IF;
    END IF;
END;
$$ LANGUAGE 'plpgsql';

--- Adds a new player, or updates the existing player's name and gender.
CREATE OR REPLACE FUNCTION UpdatePlayerRegistration(
    IN forId DiscordUser.discordId%TYPE,
    IN newUsername DiscordUser.username%TYPE,
    IN newDiscriminator DiscordUser.discriminator%TYPE,
    IN newPlayerName Player.name%TYPE,
    IN newGenderId Gender.id%TYPE,
    OUT resultId Player.id%TYPE,
    OUT wasCreated BOOLEAN)
    RETURNS RECORD
    STRICT
    VOLATILE
AS
$$
DECLARE
    playerId Player.id%TYPE;
BEGIN
    SELECT InvokingDiscordUser.playerId
    INTO STRICT playerId
    FROM GetInvokingDiscordUser(forId, newUsername, newDiscriminator)
             AS InvokingDiscordUser;
    IF playerId IS NOT NULL THEN
        wasCreated = FALSE;
        UPDATE Player
        SET name       = newPlayerName,
            genderId   = newGenderId,
            lastActive = NOW()
        WHERE id = playerId
        RETURNING id INTO resultId;
    ELSE
        wasCreated = TRUE;
        INSERT INTO Player (name, genderId, currency, joinedAt, lastActive)
        VALUES (newPlayerName, newGenderId, 100, NOW(), NOW())
        RETURNING id INTO resultId;
        UPDATE DiscordUser
        SET playerId = resultId
        WHERE discordId = forId;
    END IF;
END;
$$
    LANGUAGE 'plpgsql';
