use parking_lot::lock_api::{MutexGuard, RawMutex};
use serenity;
use serenity::model::channel::Message;
use serenity::model::guild::Guild;
use serenity::model::id::GuildId;
use serenity::prelude::RwLock as SerRwLock;
use serenity::voice::Handler;

use std::sync::Arc;

use utilities::prelude::*;

// This imports `typemap`'s `Key` as `TypeMapKey`.
use serenity::prelude::*;

use super::prelude::*;

pub fn guild(ctx: &Context, msg: &Message) -> Result<Arc<SerRwLock<Guild>>, String> {
    match msg.guild(&ctx.cache) {
        Some(guild) => Ok(guild),
        None => {
            if msg
                .channel_id
                .say(&ctx.http, "Groups and DMs not supported")
                .is_err()
            {}

            Err("failed getting Guild".to_string())
        }
    }
}

pub fn guild_id(ctx: &Context, msg: &Message) -> Result<GuildId, String> {
    let guild = guild(ctx, msg)?;
    let guild_read = guild.read();

    Ok(guild_read.id)
}

pub fn handler<'a, T: RawMutex>(
    guild_id: GuildId,
    manager: &'a mut MutexGuard<'_, T, serenity::client::bridge::voice::ClientVoiceManager>,
) -> Option<&'a mut Handler> {
    manager.get_mut(guild_id)
}

pub fn channel_contains_author(
    ctx: &mut serenity::client::Context,
    msg: &serenity::model::channel::Message,
) -> VerboseResult<()> {
    let guild = guild(ctx, msg)?;
    let guild_id = guild.read().id;

    let author_channel_id = match guild
        .read()
        .voice_states
        .get(&msg.author.id)
        .and_then(|voice_state| voice_state.channel_id)
    {
        Some(channel) => channel,
        None => create_error!("author is not in a voice channel!"),
    };

    if let Some(media) = ctx.data.read().get::<Media>() {
        let media_lock = media.lock().unwrap();
        let manager = media_lock.voice_manager.lock();

        if let Some(handler) = manager.get(guild_id) {
            // check if the bot is in a channel
            if let Some(bot_channel_id) = handler.channel_id {
                if bot_channel_id != author_channel_id {
                    create_error!("author is not in the same voice channel as the bot!");
                }
            }
        };
    }

    Ok(())
}
