using GTANetworkAPI;
using ReallifeGamemode.Server.Entities;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Factions.Medic;
using ReallifeGamemode.Server.Models;
using ReallifeGamemode.Server.Services;
using System.Linq;
using System.Text.RegularExpressions;

/**
* @overview Life of German Reallife - Faction Commands (Faction.cs)
* @author VegaZ, hydrant
* @copyright (c) 2008 - 2018 Life of German
*/

namespace ReallifeGamemode.Server.Commands
{
    class FactionCommands : Script
    {
        #region Chat Commands

        [Command("f", "~m~Benutzung: ~s~/f [Nachricht]", GreedyArg = true)]
        public void CmdFactionF(Client player, string message)
        {
            Faction f = player.GetUser()?.Faction;
            if (f == null || f.StateOwned)
            {
                ChatService.NotAuthorized(player);
                return;
            }

            message = Regex.Replace(message, "(~[a-zA-Z]~)|(!{(.*)})", "");

            string broadcastMessage = "!{02FCFF}** " + player.GetUser().GetFactionRank().RankName + " " + player.Name + ": " + message + " )) **";
            ChatService.BroadcastFaction(broadcastMessage, f);
        }

        [Command("r", "~m~Benutzung: ~s~/r [Nachricht]", GreedyArg = true)]
        public void CmdFactionR(Client player, string message)
        {
            Entities.Faction f = player.GetUser()?.Faction;
            if (f == null || !f.StateOwned)
            {
                ChatService.NotAuthorized(player);
                return;
            }

            message = Regex.Replace(message, "(~[a-zA-Z]~)|(!{(.*)})", "");

            string broadcastMessage = "!{33AA33}** " + player.GetUser().GetFactionRank().RankName + " " + player.Name + ": " + message + ", over **";
            ChatService.BroadcastFaction(broadcastMessage, f);
        }

        [Command("d", "~m~Benutzung: ~s~/d [Nachricht]", GreedyArg = true)]
        public void CmdFactionD(Client player, string message)
        {
            Faction f = player.GetUser()?.Faction;
            if (f == null || !f.StateOwned)
            {
                ChatService.NotAuthorized(player);
                return;
            }

            message = Regex.Replace(message, "(~[a-zA-Z]~)|(!{(.*)})", "");

            string broadcastMessage = "!{CC3333}** " + player.GetUser().GetFactionRank().RankName + " " + player.Name + ": " + message + ", over **";
            using (var context = new DatabaseContext())
            {
                ChatService.BroadcastFaction(broadcastMessage, context.Factions.ToList().FindAll(c => c.StateOwned));
            }
        }
        #endregion
        #region Leader Commands
        [Command("giverank", "~m~Benutzung: ~s~/giverank [Name] [Rang]", GreedyArg = true)]
        public void CmdFactionGiverank(Client player, string name, string rank)
        {
            if (player.GetUser()?.FactionId == null || player.GetUser().FactionLeader == false)
            {
                ChatService.NotAuthorized(player);
                return;
            }

            Client target = ClientService.GetClientByNameOrId(name);
            if (target == null || !target.IsLoggedIn())
            {
                ChatService.PlayerNotFound(player);
                return;
            }

            if (target.GetUser()?.FactionId != player.GetUser()?.FactionId)
            {
                ChatService.ErrorMessage(player, "Dieser Spieler ist nicht in deiner Fraktion");
                return;
            }

            using (var dbContext = new DatabaseContext())
            {
                FactionRank fr = dbContext.FactionRanks.FirstOrDefault(r => r.RankName == rank && r.FactionId == player.GetUser(dbContext).FactionId);
                if (fr == null)
                {
                    ChatService.ErrorMessage(player, "Dieser Rang existiert nicht");
                    return;
                }

                target.GetUser(dbContext).FactionRankId = fr.Id;

                ChatService.SendMessage(player, "!{02FCFF}Du hast " + target.Name + " den Rang '" + fr.RankName + "' gegeben.");
                ChatService.SendMessage(target, "!{02FCFF}Du hast von " + player.Name + " den Rang '" + fr.RankName + "' erhalten.");

                dbContext.SaveChanges();
            }
        }

        [Command("lc", "~m~Benutzung: ~s~/lc [Nachricht]", GreedyArg = true)]
        public void CmdFactionLc(Client player, string message)
        {
            if (player.GetUser()?.FactionId == null || player.GetUser().FactionLeader == false)
            {
                ChatService.NotAuthorized(player);
                return;
            }

            message = Regex.Replace(message, "(~[a-zA-Z]~)|(!{(.*)})", "");

            string broadcastMsg = "~y~[" + player.GetUser().Faction.Name + "] " + player.Name + ": " + message;

            NAPI.Pools.GetAllPlayers().ForEach(p =>
            {
                if (p.GetUser()?.FactionLeader ?? false) ChatService.SendMessage(p, broadcastMsg);
            });
        }
        #endregion
        #region Sanitäter Commands

        [Command("revive", "~m~Benutzung: ~s~/revive")]
        public void CmdFactionMedicRevive(Client player)
        {
            if (player.GetUser()?.FactionId == null || player.GetUser().FactionId != 2)
            {
                ChatService.NotAuthorized(player);
                return;
            }
            if (player.IsInVehicle)
            {
                ChatService.ErrorMessage(player, "Du kannst in einem Auto nicht wiederbeleben");
                return;
            }

            var nearPlayers = NAPI.Player.GetPlayersInRadiusOfPlayer(2, player);
            var deadPlayer = nearPlayers.Where(i => i.GetData("isDead") == true).FirstOrDefault();
            if (player == deadPlayer)
            {
                ChatService.ErrorMessage(player, "Du kannst dich nicht selbst wiederbeleben");
                return;
            }
            player.PlayAnimation("amb@medic@standing@kneel@enter", "enter", 0);

            deadPlayer.TriggerEvent("onPlayerRevived");
            deadPlayer.SendNotification("Du wurdest von ~r~" + player.Name + "~s~ wiederbelebt.");
            deadPlayer.SetData("isDead", false);
            NAPI.Player.SpawnPlayer(deadPlayer, deadPlayer.Position);
            deadPlayer.Health = 50;

            MedicTask task = Medic.ReviveTasks.FirstOrDefault(t => t.Victim == deadPlayer.Name);
            Medic.RemoveTaskFromList(task);
        }

        [Command("heal", "~m~Benutzung: ~s~/heal [Spieler]")] //TODO Eventuell noch mit Geldbetrag wie bei SA:MP
        public void CmdFactionMedicHealive(Client player, string receiver)
        {
            if (player.GetUser()?.FactionId == null || player.GetUser().FactionId != 2)
            {
                ChatService.NotAuthorized(player);
                return;
            }
            if (player.IsInVehicle)
            {
                ChatService.ErrorMessage(player, "Du kannst in einem Auto nicht heilen");
                return;
            }
            Client target = ClientService.GetClientByNameOrId(receiver);
            target.Health = 100;
            target.SendNotification("Du wurdest von ~g~" + player.Name + " ~s~geheilt.", false);
            player.SendNotification("Du hast~g~" + target.Name + " ~s~geheilt.", false);
        }
        #endregion
        #region Staatsfraktionen (LSPD / FBI) Commands
        [Command("wanted", "~m~Benutzung: ~s~/wa(nted) [Name / ID] [Anzahl] [Grund]", Alias = "wa", GreedyArg = true)]
        public void CmdFactionWanted(Client player, string nameOrId, int amount, string reason)
        {
            User user = player.GetUser();
            if (user == null || (user.FactionId != 1 && user.FactionId != 2))
            {
                ChatService.NotAuthorized(player);
                return;
            }

            if(amount <= 0)
            {
                ChatService.ErrorMessage(player, "Es muss eine positive Wantedanzahl vergeben werden");
                return;
            }

            Client target = ClientService.GetClientByNameOrId(nameOrId);
            if (target == null || !target.IsLoggedIn())
            {
                ChatService.PlayerNotFound(player);
                return;
            }

            User targetUser = target.GetUser();
            targetUser.GiveWanteds(player, amount, reason);
        }

        [Command("clear", "~m~Benutzung: ~s~/clear [Name / ID] [Grund]")]
        public void CmdFactionClear(Client player, string nameOrId, string reason)
        {

            User user = player.GetUser();
            if (user == null || (user.FactionId != 1 && user.FactionId != 2))
            {
                ChatService.NotAuthorized(player);
                return;
            }

            Client target = ClientService.GetClientByNameOrId(nameOrId);
            if (target == null || !target.IsLoggedIn())
            {
                ChatService.PlayerNotFound(player);
                return;
            }

            using (var dbContext = new DatabaseContext())
            {
                User targetUser = target.GetUser(dbContext);
                if(targetUser.Wanteds == 0)
                {
                    ChatService.ErrorMessage(player, "Der Spieler hat keine Wanteds");
                    return;
                }

                targetUser.Wanteds = 0;
                dbContext.SaveChanges();
            }
        }
        #endregion
        #region Global Fraktions Commands
        #endregion
    }
}
