use super::super::prelude::*;

use rusqlite::params;

use serenity::prelude::*;
use serenity::{
    framework::standard::{macros::command, Args, CommandResult},
    model::channel::Message,
};

#[command]
fn list(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
    if let Err(err) = channel_contains_author(ctx, msg) {
        msg.channel_id.say(&ctx.http, err)?;
        return Ok(());
    }

    let mut output = String::new();

    let data = ctx.data.read();
    let media = match data.get::<Media>() {
        Some(media) => media,
        None => {
            msg.channel_id.say(&ctx.http, "could not find media data")?;
            return Ok(());
        }
    };

    let media_lock = media.lock().unwrap();

    if args.len() == 0 {
        let playlist = media_lock.playlist();

        output += &format!(
            "{} {} queued\n",
            playlist.len(),
            if playlist.len() == 1 { "song" } else { "songs" }
        );

        let max_output = 5;

        for (i, song) in playlist.iter().enumerate() {
            if i < max_output {
                output += &format!("\t{}.\t{}\n", i + 1, song.name.clone());
            } else {
                output += &format!("\t... and {} more", playlist.len() - max_output);
                break;
            }
        }
    } else {
        let first_arg = args.single::<String>()?;

        if first_arg == "--tags" {
            // check all tables for this entry
            let mut stmt = match media_lock
                .db()
                .prepare("SELECT name FROM sqlite_master WHERE type='table'")
            {
                Ok(statement) => statement,
                Err(_) => {
                    return Err(serenity::framework::standard::CommandError(
                        "failed preparing data base access".to_string(),
                    ))
                }
            };

            let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result<String>)
            {
                Ok(rows) => rows,
                Err(_) => {
                    return Err(serenity::framework::standard::CommandError(
                        "failed querying rows".to_string(),
                    ))
                }
            };

            let mut tag_names = Vec::new();

            for row in rows {
                let table_name = match row {
                    Ok(name) => name,
                    Err(_) => {
                        return Err(serenity::framework::standard::CommandError(
                            "failed getting name from row".to_string(),
                        ))
                    }
                };

                if table_name != "Vulva3" {
                    tag_names.push(table_name);
                }
            }

            output += &format!("{} available tags:", tag_names.len());

            for tag in tag_names.iter() {
                output += &format!("\n\t{}", tag);
            }
        }
    }

    msg.channel_id.say(&ctx.http, output)?;

    Ok(())
}
