using System.Collections.Generic;
using System.Linq;
using StreamBuddy.PluginInterface;
using StreamBuddy.PluginInterface.Commands;
using StreamBuddy.PluginInterface.Features;
using StreamBuddy.PluginInterface.Users;

namespace Giveaway
{
	[Feature("Giveaway", Description = "Handles giveaways in your stream")]
	public class GiveawayFeature : IFeature
	{
		public void Enable(IStream stream)
		{

		}

		public void Disable(IStream stream)
		{
			if (stream.HasValue("GiveawayRunning"))
			{
				StreamTokens.Remove(stream);
				stream.RemoveValue("GiveawayRunning");
				stream.TempDB.DropTable<GiveawayTable>();

				stream.UserLeave -= onLeave;
				stream.OnMessage -= onMessage;
			}
		}

		static readonly Dictionary<IStream, string> StreamTokens = new Dictionary<IStream, string>();

		[Command("GOn", MinRank = UserRank.Admin, Description = "Starts a giveaway", Usage = "!gon [<token>]")]
		public void start(IUser sender, params string[] Parameters)
		{
			var stream = sender.Stream;

			if (!stream.HasValue("GiveawayToken") && Parameters.Length < 1)
			{
				sender.Reply("You've never done a giveaway before, so you need to specify a giveaway token (!gon <token>)");
				return;
			}

			bool wasRunnning = stream.HasValue("GiveawayRunning");
			if (Parameters.Length > 0)
				stream.SetValue("GiveawayToken", string.Join(" ", Parameters));

			StreamTokens[stream] = stream.GetValue<string>("GiveawayToken").ToLower();
			stream.TempDB.DropTable<GiveawayTable>();
			stream.TempDB.CreateTable<GiveawayTable>();

			stream.UserLeave += onLeave;
			stream.OnMessage += onMessage;

			stream.SetValue("GiveawayRunning", true);

			stream.SendMessage(
				(wasRunnning ? "Restarted the" : "Started a") + " giveaway, to join it include the phrase \"{0}\" in a message",
				sender.Stream.GetValue<string>("GiveawayToken"));
		}

		[Command(
			"GOff",
			MinRank = UserRank.Admin,
			Description = "Ends a current giveaway, or gets more winners",
			Usage = "!goff [<amount>]")]
		public void end(IUser sender, params string[] Parameters)
		{
			var stream = sender.Stream;
			bool wasRunnning = stream.HasValue("GiveawayRunning");

			lock (stream.TempDB)
			{
				if (stream.TempDB.Table<GiveawayTable>().Count() == 0)
					sender.Reply("Nobody entered the giveaway. At all. BibleThump");
				else
				{
					int amount = 1;
					if (Parameters.Length > 0)
						int.TryParse(Parameters[0], out amount);

					var winners = stream.TempDB.Query<GiveawayTable>(
						             "select * from GiveawayTable order by random() limit ?",
						             amount);

					if (amount > 1)
						sender.Reply(
							(wasRunnning ? "Giveaway ended, t" : "T") + "he winners are: {0}",
							string.Join(
								", ",
								winners.Select(w => stream.GetUser(w.Nick).DisplayName)));
					else
						sender.Reply(
							(wasRunnning ? "Giveaway ended, t" : "T") + "he winner is: {0}",
							stream.GetUser(winners.First().Nick).DisplayName);
				}
			}

			if (wasRunnning)
			{
				stream.RemoveValue("GiveawayRunning");

				stream.UserLeave -= onLeave;
				stream.OnMessage -= onMessage;

				StreamTokens.Remove(sender.Stream);
			}
		}

		static void onLeave(params IUser[] users)
		{
			var db = users.First().Stream.TempDB;

			db.BeginTransaction();

			foreach (IUser user in users)
				db.Delete<GiveawayTable>(user.Nick);

			db.Commit();
		}

		static void onMessage(IUser Sender, string Message)
		{
			string token = StreamTokens[Sender.Stream];
			if (Message.ToLower().Contains(token))
			{
				lock (Sender.Stream.TempDB)
				{
					Sender.Stream.TempDB.InsertOrReplace(new GiveawayTable { Nick = Sender.Nick });
				}
			}
		}
	}
}

