#[macro_use]
extern crate serenity;
extern crate rand;
extern crate sys_info;
extern crate urbandict;

use rand::Rng;
use serenity::client::Client;
use serenity::framework::standard::StandardFramework;
use serenity::model::gateway::Ready;
use serenity::prelude::*;
use std::{env, process};

struct Handler;

impl EventHandler for Handler {
    fn ready(&self, ctx: Context, ready: Ready) {
        if let Some(shard) = ready.shard {
            println!(
                "INFO: {} is connected on shard {}/{}!\n>>",
                ready.user.name, shard[0], shard[1]
            );

            use serenity::model::gateway::Game;
            use serenity::model::user::OnlineStatus;
            let game = Game::playing("with lemons");
            let status = OnlineStatus::Online;

            ctx.set_presence(Some(game), status);
        }
    }
}

fn main() {
    // Login with a bot token from the environment
    let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("token"), Handler)
        .expect("Error creating client");
    client.with_framework(
        StandardFramework::new()
            .configure(|c| c.prefix("owo ").case_insensitivity(true))
            .cmd("init", init)
            .cmd("gayculator", gayculator)
            .command("ad", |c| {
                c.cmd(ad).check(|_, msg, _, _| {
                    msg.guild_id == Some(serenity::model::id::GuildId(255386835964919810))
                })
            })
            .cmd("waffle", waffle)
            .cmd("sausage", sausage)
            .cmd("halt", halt)
            .cmd("help", help)
            .cmd("info", info)
            .cmd("ping", ping)
            .cmd("list_srv", list_srv)
            .command("compare_bot", |c| {
                c.cmd(compare_bot).known_as("compare bot")
            })
            .cmd("ship", ship)
            .cmd("uwu", uwu)
            .cmd("host", host)
            .cmd("headpat", headpat)
            .cmd("what's this", what),
    );

    // start listening for events by starting a single shard
    if let Err(e) = client.start() {
        println!("An error occurred while running the client: {:?}", e);
    }
}

command!(init(_ctx, message) {
    let num = rand::thread_rng().gen_range(0, 2);
	match num {
	0 => {
		let _ = message.channel_id.say("The Discordinator9000 is going sicko mode!");
	}
	1 => {
		let _ = message.channel_id.say("The Discordinator9000 is ready to take over the world!");
	}
	_ => {
		let _ = message.channel_id.say("Oopsie woopsie! UwU");
	}
}
});

command!(ping(_ctx, message) {
	let _ = message.reply("Pong!");
});

command!(halt(ctx, message) {
	if message.author.id == 254310746450690048 {
		use serenity::model::user::OnlineStatus;
		let status = OnlineStatus::Offline;
		ctx.set_presence(None, status);
		ctx.quit();

		use std::{thread, time};
		let one_s = time::Duration::new(2, 0);
		thread::sleep(one_s);

		process::exit(0);
	} else {
		let _ = message.channel_id.say("no");
	}
});

command!(list_srv(_ctx, message) {
	if message.author.id == 254310746450690048 {
		use serenity::CACHE;
		let cache = CACHE.read();
		let mut list = String::new();
		for (index, guild_lock) in cache.guilds.values().enumerate() {
		    let guild = guild_lock.read();
		    list.push_str(&format!("{}: {}\n", index, guild.name));
		}
		let _ = message.channel_id.say(format!("{}", list.replace("@everyone", "WARN: @ mention used as server name")));
	}
});

command!(host(_ctx, message) {
	if message.author.id == 254310746450690048 {
		let _ = message.channel_id.say(format!("Debug\nOS: {:?}\nHost: {:?}", sys_info::os_type().unwrap(), sys_info::hostname().unwrap()));
	}
});

command!(ship(_ctx, message, args) {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

	let first = calculate_hash(&args.single::<String>().unwrap());
	let second = calculate_hash(&args.single::<String>().unwrap());
	let mut slider = String::new();
	let res = (first % second) / 100000000000000000;

	let mut num = 0;
	while num < res / 10 {
		slider.push('▬');
		num += 1;
	}
		slider.push_str(":heart:");
	num = 0;
	while num < (10 - res / 10) {
		slider.push('▬');
		num += 1;
	}
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
			.title(format!("{}%", res))
			.description(slider)
			.color(0xff00ce)
		));

	fn calculate_hash<T: Hash>(t: &T) -> u64 {
	    let mut s = DefaultHasher::new();
	    t.hash(&mut s);
	    s.finish()
	}
});

command!(headpat(_ctx, message, args) {
	message.channel_id.send_message(|m|
        m.embed(|e|
            e.title(format!("Sending headpats to **{}**...", args.trim().to_string()))
             .image("https://i.pinimg.com/originals/83/1a/90/831a903eab6d827dcfd298b9e3196e30.jpg")
             .description("[Source](https://www.pinterest.com/pin/377809856242075277/)"))
            ).expect("Failed to send message!");
});

command!(uwu(_ctx, message) {
	let num = rand::thread_rng().gen_range(0, 4);
	match num {
	0 => {
		let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
		.image("https://i.redditmedia.com/qDD9W7NJqTAk31y061TuRW9R8qOcCuEmmCWyOsUEavE.png?fit=crop&crop=faces%2Centropy&arh=2&w=640&s=ebdd3f1970b4fe70ccd24a1958e7fc32")
	)); }
	1 => {
		let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
		.image("https://www.shitpostbot.com/img/sourceimages/smash-that-mfuckn-uwu-button-57b5aa1de9fe4.jpeg")
	)); }
	2 => {
		let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
		.image("https://www.shitpostbot.com/img/sourceimages/fallout-nv-owo-57e586ae15322.jpeg")
	)); }
	3 => {
		let _ = message.channel_id.send_message(|m| m
			.embed(|e| e
			.image("https://i.redditmedia.com/-JaK9YW7mPz2S2xBJmXvW4fZ58uGMa4l6GIgYt3dqZg.jpg?fit=crop&crop=faces%2Centropy&arh=2&w=640&s=ebab29a577346b4d18ec914538b69bb4")
		)); }
	_ => {
	 	let _ = message.channel_id.say("UwU");
	 }
	}
});

command!(gayculator(_ctx, message, args) {
if message.author.id != 191948420141809665 {
	let number_32: i32 = args.trim().parse().unwrap_or(1);
	let mut result;
	if number_32 % 2 == 0 {
		result = "You are straight as heck!".to_string();
	} else {
		result = "You are hella gay!".to_string();
	}
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
		.title("Gayness level:")
		.description(result)
		.color(0xff00f9)
	));
 }
});

/* command!(notice(ctx, message, args) {
    let query: String = args.trim().parse().expect("ERR");
    let query = query.replace(" ", "+");
    let link = String::from(format!("https://www.google.com/search?q={}&source=lnms&tbm=isch", query));
}); */

command!(waffle(_ctx, message) {
	let _ = message.channel_id.say("h");
});

command!(sausage(_ctx, message) {
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
		.title("Dongle!")
		.image("https://cdn.discordapp.com/attachments/379673147764506624/431546724637736971/image.png"))
		);
});

command!(ad(_ctx, message) {
		let _ = message.channel_id.send_message(|m| m
			.embed(|e| e
			.title(":b:ottom text")
			.description("hey @\u{200B}everyone , JOIN OUR SUPER KOOL SERVER ON 1.5.2 CRACKED SERVER MARRIAGE GAY DRUGS TOWN OF SALEM PLUGINS ECONOMY NO GRIEF PROTECTION BETTER THAN HYPIXAL SUPPORTS EMOJI FREE OP CSGO PVP SKYWARS SKYBLOCC BLOCKCHAIN AR VR TENSORFLOW IoT QUANTUM COMPUTER SERVERLESS DARK DATA JAVA ALSO ITS LIKE ROBLOX AAAAA JOIN AT superkool.[B].cc OwO (edited)(edited)(edited)(edited)(edited)(edited)(edited)")
			.thumbnail("https://i.imgur.com/8MU0gqD.png")
			.color(0x00f3ff))
		);
});

command!(help(_ctx, message) {
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
			.title("Availble commands:")
			.description("All commands are case-insensitive")
			.fields(vec![
				("owo init", "Introduce me", false),
				("owo ping", "Pong", false),
				("owo waffle", "stroopwafel owo", false),
				("owo sausage", "sosig", false),
				("owo help", "Help the fellow humanz!", false),
				("owo info", "Show information about me!", false),
				("owo compare_bot ``bot's name``", "Compare me to other robots!", false),
				("owo what's this ``word``", "Find a definition of word", false),
				("owo ship ``name 1`` ``name 2``", "*shipping intensifies*", false),
                ("owo headpat ``name``", "Headpat someone", false),
				("Admin commands:", "\u{200B}", true),
				("owo halt", "kill me", false),
				("owo list_srv", "list my servers", false),
				("owo host", "Display host info", false)
			])
			.color(0x000000)
			));
});

command!(info(_ctx, message) {
use serenity::CACHE;
let num = CACHE.read().guilds.len();
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
			.title("Discordinator9000's info:")
			.description("h")
			.field("Author:", "#9000", false)
			.field("Server count:", num  , false)
			.field("Invite:", "[Invite link](https://discordapp.com/api/oauth2/authorize?client_id=470350233419907129&permissions=2048&scope=bot)", false )
			.footer(|f| f
			.text("Written in Rust using Serenity library"))
			.color(0xee657)
			));
});

command!(compare_bot(_ctx, message, args) {
if message.author.id != 191948420141809665 {
let text: String = args.trim().parse()
	.expect("ERR!");
	if text.to_lowercase().contains("nib") {
		let _ = message.channel_id.say("I am superior to NibBot");
	} else if text.to_lowercase().contains("amit") {
		let _ = message.channel_id.say("Amiter is big dumb");
	} else if text.to_lowercase().contains("discordinator") {
		let _ = message.channel_id.say("Option<(!, ())>");
	} else {
		let _ = message.channel_id.say(format!("Me and {} are friends!", text));
	}
}
});

command!(what(_ctx, message, args){
	let text: String = args.trim().parse().expect("ERR");
	let defs = &urbandict::get_definitions(&format!("{}", text))?;
	let def = &defs[0];
	let _ = message.channel_id.send_message(|m| m
		.embed(|e| e
			.title(format!("Author: {}", def.author))
			.field("Definition: ", def.definition.replace(|c| c == '[' || c == ']', ""), false)
		));
});
