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

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

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

            Concilium.Data.Resistance.GameOver += () =>
            {
                Concilium.Data.Resistance = null;
            };
            Concilium.Data.Resistance.OnLobbyNotice += (notice) =>
            {
                Client.LocalUser.SendMessage(ResistanceChannel, notice);
            };
            Concilium.Data.Resistance.OnUsersNotice += (users, notice) =>
            {
                foreach (var user in users)
                    Client.LocalUser.SendMessage(user, notice);
            };

            Concilium.Data.Resistance.CheckState();
        }

        public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
        {
            if (_parameters.Count == 0)
            {
                Client.GetChannel(ResistanceChannel).Invite(_sSource);
                return;
            }

            var action = _parameters[0];
            if (action == "admin" && (_sSource == "Concilium" || _sSource == "xTr1m"))
            {
                action = _parameters[0];
                _sSource = _parameters[1];
                _parameters = _parameters.Skip(2).ToList();
            }

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

            if (action == "help")
            {
                if (_parameters.Count == 1)
                    Client.LocalUser.SendMessage(_sSource, "Resistance commands: help, create, reset, join, agree, disagree, team, execute, sabotage, status, missions. Use \".resist 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 The Resistance game. Expects no _parameters.");
                    }
                    else if (helpAction == "reset")
                    {
                        Client.LocalUser.SendMessage(_sSource, "The creator of a The Resistance game can shut it down.");
                    }
                    else if (helpAction == "start")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Starts a The Resistance game when at least 5 players have joined. Expects no parameter.");
                    }
                    else if (helpAction == "join")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Join the current The Resistance game. Expects no _parameters.");
                    }
                    else if (helpAction == "status")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Announces the current game status.");
                    }
                    else if (helpAction == "agree")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby agrees with the team proposed by the leader.");
                    }
                    else if (helpAction == "team")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Only via query. The leader hereby declares his or her team members.");
                    }
                    else if (helpAction == "disagree")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby disagrees with the team proposed by the leader.");
                    }
                    else if (helpAction == "execute")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby helps to execute the mission.");
                    }
                    else if (helpAction == "sabotage")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Only via query. The player hereby sabotages the mission. Can only be done by spies.");
                    }
                    else if (helpAction == "missions")
                    {
                        Client.LocalUser.SendMessage(_sSource, "Posts the mission Concilium.Data defined in the rules for this game (amount of team members and sabotages per mission).");
                    }
                    else
                    {
                        Client.LocalUser.SendMessage(_sSource, "There's no such command available in The Resistance.");
                    }
                }
            }
            else if (action == "reset")
            {
                if (Concilium.Data.Resistance != null && _sTarget == null && (_sSource == Concilium.Data.Resistance.GameCreator || _sSource == "xTr1m"))
                {
                    Client.LocalUser.SendMessage(ResistanceChannel, "This The Resistance game was shut down. (reset command used by " + Concilium.Data.Resistance.GameCreator + ")");
                    Concilium.Data.Resistance = null;
                }
            }
            else if (action == "create")
            {
                if (Concilium.Data.Resistance != null)
                    return;

                Concilium.Data.Resistance = new Resistance();
                Load();
                Concilium.Data.Resistance.Init(_sSource);

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

                Concilium.Data.Resistance.StartGame(_sSource);
            }
            else if (action == "join")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

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

                Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), Concilium.Data.Resistance.GetStatus());
            }
            else if (action == "agree")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

                if (_sTarget == "Concilium")
                    Concilium.Data.Resistance.AgreeTeam(_sSource);
                else
                    Client.LocalUser.SendMessage(ResistanceChannel, "Agree only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
            }
            else if (action == "team")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

                if (_sTarget == "Concilium")
                    Concilium.Data.Resistance.SetTeamMembers(_sSource, _parameters.Skip(1));
                else
                    Client.LocalUser.SendMessage(ResistanceChannel, "Set up a team only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
            }
            else if (action == "disagree")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

                if (_sTarget == "Concilium")
                    Concilium.Data.Resistance.DisagreeTeam(_sSource);
                else
                    Client.LocalUser.SendMessage(ResistanceChannel, "Disagree only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
            }
            else if (action == "execute")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

                if (_sTarget == "Concilium")
                    Concilium.Data.Resistance.ExecuteMission(_sSource);
                else
                    Client.LocalUser.SendMessage(ResistanceChannel, "Execute mission only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
            }
            else if (action == "sabotage")
            {
                if (Concilium.Data.Resistance == null)
                {
                    Client.LocalUser.SendMessage(_sSource, "There's currently no running The Resistance game.");
                    return;
                }

                if (_sTarget == "Concilium")
                    Concilium.Data.Resistance.SabotageMission(_sSource);
                else
                    Client.LocalUser.SendMessage(ResistanceChannel, "Sabotage mission only via PM. " + _sSource + "'s command was " + (char)2 + "not" + (char)2 + "executed");
            }
        }
    }
}
