﻿using Oxide.Core.Libraries.Covalence;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Oxide.Plugins
{
    [Info("SD Teleportation", "Mroczny", "0.1.4")]
    [Description("Teleportation for 7 Days to Die")]
    class SDTeleportation : CovalencePlugin
    {
        private readonly Dictionary<string, Vector3> deathPosition = new Dictionary<string, Vector3>();

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Misc - No Permission"] = "You dont have permission to use this command.",
                ["Misc - Unknown Player"] = "Unknown player: [FBEED1]{0}",

                ["TP - Syntax_1"] = "/tp <targetplayer>",
                ["TP - Syntax_2"] = "/tp <player> <targetplayer>",
                ["TP - Syntax_3"] = "/tp <x> <y> <z>",
                ["TP - Syntax_4"] = "/tp <player> <x> <y> <z>",

                ["TP - To Player"] = "Teleported to [FBEED1]{0}",
                ["TP - Player To Player"] = "Teleported [FBEED1]{0}[FFFFFF] to [FBEED1]{1}",
                ["TP - To Position"] = "Teleported to [FBEED1]{0}",
                ["TP - Player To Position"] = "Teleported [FBEED1]{0}[FFFFFF] to [FBEED1]{1}",

                ["TPHere - Syntax"] = "/tphere <player>",
                ["TPHere - Player To Sender"] = "Teleported [FBEED1]{0}[FFFFFF] to you",

                ["Back - Teleport"] = "Teleported back to previous location",
                //["Back - Respawn Notify"] = "Use the [FBEED1]/back[FFFFFF] command to return to your death point.",
                ["Back - Player Death"] = "You can only use [FBEED1]/back[FFFFFF] after respawning!",
                ["Back - No Saved Location"] = "There is no sign of your previous location present in our database.",

                //["Reason - No Landclaim"]
                ["Reason - Death"] = "[FBEED1]{0}[FFFFFF] is dead",
                ["Reason - Death Self"] = "You are dead",
            }, this);

            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Misc - No Permission"] = "Nie posiadasz uprawnień do tej komendy.",
                ["Misc - Unknown Player"] = "Nieznany gracz: [FBEED1]{0}",

                ["TP - Syntax_1"] = "/tp <gracz>",
                ["TP - Syntax_2"] = "/tp <gracz> <gracz>",
                ["TP - Syntax_3"] = "/tp <x> <y> <z>",
                ["TP - Syntax_4"] = "/tp <gracz> <x> <y> <z>",

                ["TP - To Player"] = "Zostałeś teleportowany do [FBEED1]{0}",
                ["TP - Player To Player"] = "Teleportowano [FBEED1]{0}[FFFFFF] do [FBEED1]{1}",
                ["TP - To Position"] = "Zostałeś teleportowany na [FBEED1]{0}",
                ["TP - Player To Position"] = "Teleportowano [FBEED1]{0}[FFFFFF] na [FBEED1]{1}",

                ["TPHere - Syntax"] = "/tphere <gracz>",
                ["TPHere - Player To Sender"] = "Teleportowano [FBEED1]{0}[FFFFFF] do Ciebie",

                ["Back - Teleport"] = "Zostałeś teleportowany z powrotem do poprzedniej lokacji",
                //["Back - Respawn Notify"] = "Use the [FBEED1]/back[FFFFFF] command to return to your death point.",
                ["Back - Player Death"] = "Możesz użyć [FBEED1]/back[FFFFFF] tylko po odrodzeniu!",
                ["Back - No Saved Location"] = "Nie ma zapisanej Twojej poprzedniej lokalizacji.",

                //["Reason - No Landclaim"]
                ["Reason - Death"] = "[FBEED1]{0}[FFFFFF] nie żyje",
                ["Reason - Death Self"] = "Nie żyjesz",
            }, this, "pl");
        }

        private void Loaded()
        {
            permission.RegisterPermission("sdteleportation.tp", this);
            permission.RegisterPermission("sdteleportation.tphere", this);
            permission.RegisterPermission("sdteleportation.back", this);
        }

        [Command("tp")]
        private void TeleportCommand(IPlayer player, string command, string[] args)
        {
            if (player.HasPermission("sdteleportation.tp") || player.IsAdmin)
            {
                EntityPlayer entityPlayer = player.Object as EntityPlayer;
                //bool LandProtectionPlayer = GameManager.Instance.World.CanPlaceBlockAt(Vector3i.FromVector3Rounded(entityPlayer.transform.position), GameManager.Instance.GetPersistentPlayerList().GetPlayerDataFromEntityID(entityPlayer.entityId));

                if (args.Length == 0 || args.Length > 4)
                {
                    player.Reply(Lang("TP - Syntax_1", player.Id));
                    player.Reply(Lang("TP - Syntax_2", player.Id));
                    player.Reply(Lang("TP - Syntax_3", player.Id));
                    player.Reply(Lang("TP - Syntax_4", player.Id));
                }
                if (args.Length == 1)
                {
                    ClientInfo cTarget = ConsoleHelper.ParseParamIdOrName(players.FindPlayer(args[0]).Name);
                    if (cTarget != null)
                    {
                        if (!entityPlayer.IsDead())
                        {
                            EntityPlayer target = GameManager.Instance.World.Players.dict[cTarget.entityId];
                            Teleport(entityPlayer, target.transform.position);
                            player.Reply(string.Format(Lang("TP - To Player", player.Id), target.EntityName));
                        }
                        else
                        {
                            player.Reply(string.Format(Lang("Reason - Death Self", player.Id)));
                        }
                    }
                    else
                    {
                        player.Reply(string.Format(Lang("Misc - Unknown Player", player.Id), args[0]));
                    }
                }
                if (args.Length == 2)
                {
                    ClientInfo cFrom = ConsoleHelper.ParseParamIdOrName(players.FindPlayer(args[0]).Name);
                    ClientInfo cTo = ConsoleHelper.ParseParamIdOrName(players.FindPlayer(args[1]).Name);
                    if (cFrom != null)
                    {
                        if (cTo != null)
                        {
                            EntityPlayer playerFrom = GameManager.Instance.World.Players.dict[cFrom.entityId];
                            EntityPlayer playerTo = GameManager.Instance.World.Players.dict[cTo.entityId];
                            if (!playerFrom.IsDead())
                            {
                                if (!playerTo.IsDead())
                                {
                                    Teleport(playerFrom, playerTo.transform.position);
                                    Debug.Log($"Teleported {playerFrom.EntityName} to {playerTo.EntityName}");
                                    player.Reply(string.Format(Lang("TP - Player To Player", player.Id), playerFrom.EntityName, playerTo.EntityName));
                                }
                                else
                                {
                                    player.Reply(string.Format(Lang("Reason - Death", player.Id), playerTo.EntityName));
                                }
                            }
                            else
                            {
                                player.Reply(string.Format(Lang("Reason - Death", player.Id), playerFrom.EntityName));
                            }
                        }
                        else
                        {
                            player.Reply(string.Format(Lang("Misc - Unknown Player", player.Id), args[1]));
                        }
                    }
                    else
                    {
                        player.Reply(string.Format(Lang("Misc - Unknown Player", player.Id), args[0]));
                    }
                }
                if (args.Length == 3)
                {
                    Vector3 position = new Vector3(Convert.ToSingle(args[0]), Convert.ToSingle(args[1]), Convert.ToSingle(args[2]));
                    Teleport(entityPlayer, position);
                    player.Reply(string.Format(Lang("TP - To Position", player.Id), position));
                }
                if (args.Length == 4)
                {
                    ClientInfo cTarget = ConsoleHelper.ParseParamIdOrName(players.FindPlayer(args[0]).Name);
                    if (cTarget != null)
                    {
                        EntityPlayer target = GameManager.Instance.World.Players.dict[cTarget.entityId];
                        Vector3 position = new Vector3(Convert.ToSingle(args[1]), Convert.ToSingle(args[2]), Convert.ToSingle(args[3]));

                        Teleport(target, position);
                        player.Reply(string.Format(Lang("TP - Player To Position", player.Id), cTarget.playerName, position));
                    }
                    else
                    {
                        player.Reply(string.Format(Lang("Misc - Unknown Player", player.Id), args[0]));
                    }
                }
            }
            else
            {
                player.Reply(Lang("Misc - No Permission", player.Id));
            }
        }

        [Command("tphere")]
        private void TeleportHereCommand(IPlayer player, string command, string[] args)
        {
            if (player.HasPermission("sdteleportation.tphere") || player.IsAdmin)
            {
                EntityPlayer entityPlayer = player.Object as EntityPlayer;
                if (args.Length == 0 || args.Length > 1)
                {
                    player.Reply(string.Format(Lang("TPHere - Syntax", player.Id)));
                }
                if (args.Length == 1)
                {
                    ClientInfo cTarget = ConsoleHelper.ParseParamIdOrName(players.FindPlayer(args[0]).Name);
                    if (cTarget != null)
                    {
                        EntityPlayer target = GameManager.Instance.World.Players.dict[cTarget.entityId];
                        if (!target.IsDead())
                        {
                            Teleport(target, entityPlayer.transform.position);
                            player.Reply(string.Format(Lang("TPHere - Player To Sender", player.Id), cTarget.playerName));
                        }
                        else
                        {
                            player.Reply(string.Format(Lang("Reason - Death", player.Id), cTarget.playerName));
                        }
                    }
                    else
                    {
                        player.Reply(string.Format(Lang("Misc - Unknown Player", player.Id), args[0]));
                    }
                }
            }
            else
            {
                player.Reply(Lang("Misc - No Permission", player.Id));
            }
        }

        [Command("back")]
        private void BackCommand(IPlayer player, string command, string[] args)
        {
            if (player.HasPermission("sdteleportation.back") || player.IsAdmin)
            {
                EntityPlayer entityPlayer = player.Object as EntityPlayer;
                if (deathPosition.ContainsKey(player.Id))
                {
                    if (!entityPlayer.IsDead())
                    {
                        Teleport(entityPlayer, deathPosition[player.Id]);

                        //if (config.ClearBackAfterExecute) { }
                        //deathPosition.Remove(player.Id);

                        player.Reply(string.Format(Lang("Back - Teleport", player.Id)));
                    }
                    else
                    {
                        player.Reply(string.Format(Lang("Back - Player Death", player.Id)));
                    }
                }
                else
                {
                    player.Reply(string.Format(Lang("Back - No Saved Location", player.Id)));
                }
            }
            else
            {
                player.Reply(Lang("Misc - No Permission", player.Id));
            }
        }

        private void Teleport(EntityPlayer player, Vector3 position)
        {
            ClientInfo entityPlayer = ConsoleHelper.ParseParamEntityIdToClientInfo(player.entityId.ToString());

            NetPackageTeleportPlayer package = NetPackageManager.GetPackage<NetPackageTeleportPlayer>().Setup(position);
            entityPlayer.SendPackage(package);
        }

        private void OnEntityDeath(Entity entity, DamageResponse response)
        {
            if (entity != null && entity.IsClientControlled())
            {
                ClientInfo cInfo = ConsoleHelper.ParseParamEntityIdToClientInfo(entity.entityId.ToString());
                if (cInfo.IPlayer.HasPermission("sdteleportation.back") || cInfo.IPlayer.IsAdmin)
                {
                    deathPosition[cInfo.InternalId.ReadablePlatformUserIdentifier] = entity.transform.position;
                }
            }
        }

        private string Lang(string msg, object SteamId = null, params object[] args) => lang.GetMessage(msg, this, SteamId.ToString());

        /* Maybe Later
        void OnPlayerRespawned(ClientInfo cInfo, string reason)
        {
            Puts(cInfo.InternalId.ReadablePlatformUserIdentifier);
            if (cInfo.IPlayer.HasPermission("sdteleportation.back") || cInfo.IPlayer.IsAdmin)
            {
                if (deathPosition.ContainsKey(cInfo.InternalId.ReadablePlatformUserIdentifier))
                {
                    player.Reply(Lang("Back - Respawn Notify", player.Id));
                }
            }
        }*/
    }
}