using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Concilium.Bot.Features
{
    [BotFeature(".mafia")]
    public class MafiaFeature : BotFeatureBase
    {
        public static string MafiaChannel = "#sppro.mafia";

        public override void Load()
        {
            var channel = Client.GetChannel(MafiaChannel);
            if (channel == null)
            {
                Client.Channels.Join(MafiaChannel);
                channel = Client.GetChannel(MafiaChannel);
            }

            Concilium.Data.Mafia.DayBegins += () =>
            {
                foreach (var user in channel.Users)
                    user.Voice();
            };
            Concilium.Data.Mafia.NightBegins += () =>
            {
                foreach (var user in channel.Users)
                    user.DeVoice();
            };
            Concilium.Data.Mafia.OnUserJoined += (nickName) =>
            {
                channel.Users.First(u => u.User.NickName == nickName).Voice();
            };
            Concilium.Data.Mafia.OnUserDied += (nickName) =>
            {
                channel.Users.First(u => u.User.NickName == nickName).DeVoice();
            };
            Concilium.Data.Mafia.GameOver += () =>
            {
                foreach (var user in channel.Users)
                    user.DeVoice();

                Concilium.Data.Mafia = null;
                channel.SetModes("-m");
            };
            Concilium.Data.Mafia.OnLobbyNotice += (notice) =>
            {
                Client.LocalUser.SendMessage(MafiaChannel, notice);
            };
            Concilium.Data.Mafia.OnUsersNotice += (users, notice) =>
            {
                foreach (var user in users)
                    Client.LocalUser.SendMessage(user, notice);
            };

            Concilium.Data.Mafia.CheckState();
        }

        public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
        {
            if (_parameters.Count == 0)
            {
                Client.LocalUser.SendMessage(_sSource, "Mafia is played at the " + MafiaChannel + " channel.");
                Client.GetChannel(MafiaChannel).Invite(_sSource);
                return;
            }

            if (_sTarget != null && _sTarget != MafiaChannel)
            {
                Client.LocalUser.SendMessage(_sSource, "Mafia is played at the " + MafiaChannel + " channel.");
                Client.GetChannel(MafiaChannel).Invite(_sSource);
                return;
            }

            var action = _parameters[0];
            if (action == "help")
            {
                if (_parameters.Count == 1)
                    Client.LocalUser.SendMessage(_sSource, "Mafia commands: help, create, join, vote, unvote, detect, save, status, kill. Use \".mafia help %command%\" to learn more.");
                else
                {
                    var helpAction = _parameters[1];
                    if (helpAction == "help")
                    {
                        Client.LocalUser.SendMessage(_sSource, string.Format("Are you dumb, {0}?", _sSource));
                    }
                    else if (helpAction == "create")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Creates a new mafia game. Expects no _parameters.");
                    }
                    else if (helpAction == "start")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Starts a mafia game when at least 5 players have joined. Expects no parameter.");
                    }
                    else if (helpAction == "join")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Join the current mafia game. Expects no _parameters.");
                    }
                    else if (helpAction == "vote")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Places a vote. May be used several times. Parameter: The nick name of the player you're voting for.");
                    }
                    else if (helpAction == "unvote")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Removes your vote if it exists.");
                    }
                    else if (helpAction == "detect")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Detectives can discover if one player is a mafioso once each night. Parameter: The nick name of the player you're detecting.");
                    }
                    else if (helpAction == "save")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Doctors can rescue one player from a possible mafioso assault. Parameter: The nick name of the player you're detecting.");
                    }
                    else if (helpAction == "kill")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Vigilantes can kill one player at will during the night. Parameter: The nick name of the player to be killed.");
                    }
                    else if (helpAction == "status")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Announces the current game status.");
                    }
                    else
                    {
                        Client.LocalUser.SendMessage(_sSource, "There's no such command available in mafia.");
                    }
                }
            }
            else if (action == "reset")
            {
                if (Concilium.Data.Mafia != null && _sTarget == "Concilium" && _sSource == Concilium.Data.Mafia.GameCreator)
                {
                    Client.LocalUser.SendMessage(MafiaChannel, "The mafia game was shut down. (reset command used by " + Concilium.Data.Mafia.GameCreator + ")");
                    Concilium.Data.Mafia = null;
                }
            }
            else if (action == "create")
            {
                if (Concilium.Data.Mafia != null)
                    return;

                Concilium.Data.Mafia = new Mafia();
                Load();
                Concilium.Data.Mafia.Init(_sSource);
                foreach (var user in Client.GetChannel(MafiaChannel).Users)
                    user.DeVoice();

                foreach (var channel in Client.Channels)
                {
                    if (channel.Name != MafiaChannel)
                        Client.LocalUser.SendMessage(channel, "A mafia game was just created! If you'd like to play, join " + MafiaChannel + " now!");
                }
            }
            else if (action == "start")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                Concilium.Data.Mafia.StartGame(_sSource);
                Client.GetChannel(MafiaChannel).SetModes("+m");
            }
            else if (action == "join")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                Concilium.Data.Mafia.JoinPlayer(_sSource);
            }
            else if (action == "kill")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                if (_sTarget == "Concilium")
                {
                    Client.LocalUser.SendMessage(_sSource, "Kill only via query!");
                }
                else
                {
                    if (_parameters.Count != 2)
                        Client.LocalUser.SendMessage(_sSource, "Vigilantes can kill one player at will during the night. Parameter: The nick name of the player to be killed.");
                    else
                    {
                        Concilium.Data.Mafia.VoteVigilanteKill(_sSource, _parameters[1]);
                    }
                }
            }
            else if (action == "vote")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                if (_sTarget == "Concilium")
                {
                    Client.LocalUser.SendMessage(_sSource, "Place a vote only via query!");
                }
                else
                {
                    if (_parameters.Count != 2)
                        Client.LocalUser.SendMessage(_sSource, "Places a vote. May be used several times. Parameter: The nick name of the player you're voting for.");
                    else
                    {
                        Concilium.Data.Mafia.PlayerVote(_sSource, _parameters[1]);
                    }
                }
            }
            else if (action == "unvote")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                Concilium.Data.Mafia.Unvote(_sSource);
            }
            else if (action == "detect")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                if (_sTarget == "Concilium")
                {
                    Client.LocalUser.SendMessage(_sSource, "Detective work should only be done via query!");
                }
                else
                {
                    if (_parameters.Count != 2)
                        Client.LocalUser.SendMessage(_sSource, "Detectives can discover if one player is a mafioso once each night. Parameter: The nick name of the player you're detecting.");
                    else
                    {
                        Concilium.Data.Mafia.DetectMafioso(_sSource, _parameters[1]);
                    }
                }
            }
            else if (action == "save")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                if (_sTarget == "Concilium")
                {
                    Client.LocalUser.SendMessage(_sSource, "Doctor work should only be done via query!");
                }
                else
                {
                    if (_parameters.Count != 2)
                        Client.LocalUser.SendMessage(_sSource, "Doctors can rescue one player from a possible mafioso assault. Parameter: The nick name of the player you're detecting.");
                    else
                    {
                        Concilium.Data.Mafia.SaveCivilist(_sSource, _parameters[1]);
                    }
                }
            }
            else if (action == "status")
            {
                if (Concilium.Data.Mafia == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running mafia game.");
                    return;
                }

                Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), Concilium.Data.Mafia.GetStatus());
            }
        }
    }
}
