using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Auto Doors", "Wulf/lukespragg/Arainrr/James/Bushhy", "3.3.11", ResourceId = 1924)]
    [Description("Automatically closes doors behind players after X seconds")]
    public class AutoDoors : RustPlugin
    {
        #region Fields

        [PluginReference] private Plugin RustTranslationAPI;
        private const string PERMISSION_USE = "autodoors.use";
        private readonly Hash<ulong, Timer> doorTimers = new Hash<ulong, Timer>();
        private readonly Dictionary<string, string> supportedDoors = new Dictionary<string, string>();
        private HashSet<DoorManipulator> doorManipulators;

        #endregion Fields

        #region Oxide Hooks

        private void Init()
        {
            LoadData();
            Unsubscribe(nameof(OnEntitySpawned));
            permission.RegisterPermission(PERMISSION_USE, this);
            if (configData.chatS.commands.Length == 0)
            {
                configData.chatS.commands = new[] { "ad" };
            }
            foreach (var command in configData.chatS.commands)
            {
                cmd.AddChatCommand(command, this, nameof(CmdAutoDoor));
            }
        }

        private void OnServerInitialized()
        {
            UpdateConfig();
            if (configData.globalS.excludeDoorController)
            {
                doorManipulators = new HashSet<DoorManipulator>();
                Subscribe(nameof(OnEntitySpawned));
                foreach (var doorManipulator in BaseNetworkable.serverEntities.OfType<DoorManipulator>())
                {
                    OnEntitySpawned(doorManipulator);
                }
            }
        }

        private void OnEntitySpawned(DoorManipulator doorManipulator)
        {
            if (doorManipulator == null || doorManipulator.OwnerID == 0) return;
            doorManipulators.Add(doorManipulator);
        }

        private void OnEntityKill(DoorManipulator doorManipulator)
        {
            if (doorManipulator == null || doorManipulators == null) return;
            doorManipulators.RemoveWhere(x => x == doorManipulator);
        }

        private void OnEntityKill(Door door)
        {
            if (door == null || door.net == null) return;
            var doorID = door.net.ID.Value;
            Timer value;
            if (doorTimers.TryGetValue(doorID, out value))
            {
                value?.Destroy();
                doorTimers.Remove(doorID);
            }
            foreach (var playerData in storedData.playerData.Values)
            {
                playerData.theDoorS.Remove(doorID);
            }
        }

        private void OnServerSave() => timer.Once(UnityEngine.Random.Range(0f, 60f), SaveData);

        private void Unload()
        {
            foreach (var value in doorTimers.Values)
            {
                value?.Destroy();
            }
            SaveData();
        }

        private void OnDoorOpened(Door door, BasePlayer player)
        {
            if (door == null || door.net == null || !door.IsOpen()) return;
            if (!supportedDoors.ContainsKey(door.ShortPrefabName)) return;
            if (!configData.globalS.useUnownedDoor && door.OwnerID == 0) return;
            if (configData.globalS.excludeDoorController && HasDoorController(door)) return;
            if (configData.usePermission && !permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) return;

            var playerData = GetPlayerData(player.userID, true);
            if (!playerData.doorData.enabled) return;
            float autoCloseTime;
            var doorID = door.net.ID.Value;
            StoredData.DoorData doorData;
            if (playerData.theDoorS.TryGetValue(doorID, out doorData))
            {
                if (!doorData.enabled) return;
                autoCloseTime = doorData.time;
            }
            else if (playerData.doorTypeS.TryGetValue(door.ShortPrefabName, out doorData))
            {
                if (!doorData.enabled) return;
                autoCloseTime = doorData.time;
            }
            else autoCloseTime = playerData.doorData.time;

            if (autoCloseTime <= 0) return;
            if (Interface.CallHook("OnDoorAutoClose", player, door) != null) return;

            Timer value;
            if (doorTimers.TryGetValue(doorID, out value))
            {
                value?.Destroy();
            }
            doorTimers[doorID] = timer.Once(autoCloseTime, () =>
            {
                doorTimers.Remove(doorID);
                if (door == null || !door.IsOpen()) return;
                if (configData.globalS.cancelOnKill && player != null && player.IsDead()) return;
                door.SetFlag(BaseEntity.Flags.Open, false);
                door.SendNetworkUpdateImmediate();
            });
        }

        private void OnDoorClosed(Door door, BasePlayer player)
        {
            if (door == null || door.net == null || door.IsOpen()) return;
            Timer value;
            if (doorTimers.TryGetValue(door.net.ID.Value, out value))
            {
                value?.Destroy();
                doorTimers.Remove(door.net.ID.Value);
            }
        }

        #endregion Oxide Hooks

        #region Methods

        private bool HasDoorController(Door door)
        {
            foreach (var doorManipulator in doorManipulators)
            {
                if (doorManipulator != null && doorManipulator.targetDoor == door)
                {
                    return true;
                }
            }
            return false;
        }

        private StoredData.PlayerData GetPlayerData(ulong playerID, bool readOnly = false)
        {
            StoredData.PlayerData playerData;
            if (!storedData.playerData.TryGetValue(playerID, out playerData))
            {
                playerData = new StoredData.PlayerData
                {
                    doorData = new StoredData.DoorData
                    {
                        enabled = configData.globalS.defaultEnabled,
                        time = configData.globalS.defaultDelay,
                    }
                };
                if (readOnly)
                {
                    return playerData;
                }
                storedData.playerData.Add(playerID, playerData);
            }

            return playerData;
        }

        private static Door GetLookingAtDoor(BasePlayer player)
        {
            RaycastHit rHit;
            if (Physics.Raycast(player.eyes.HeadRay(), out rHit, 10f, Rust.Layers.Mask.Construction))
            {
                return rHit.GetEntity() as Door;
            }
            return null;
        }

        private void UpdateConfig()
        {
            foreach (var itemDefinition in ItemManager.GetItemDefinitions())
            {
                var itemModDeployable = itemDefinition.GetComponent<ItemModDeployable>();
                if (itemModDeployable == null) continue;
                var door = GameManager.server.FindPrefab(itemModDeployable.entityPrefab.resourcePath)?.GetComponent<Door>();
                if (door == null || string.IsNullOrEmpty(door.ShortPrefabName)) continue;
                ConfigData.DoorSettings doorSettings;
                if (!configData.doorS.TryGetValue(itemDefinition.shortname, out doorSettings))
                {
                    doorSettings = new ConfigData.DoorSettings
                    {
                        enabled = true,
                        displayName = itemDefinition.displayName.english
                    };
                    configData.doorS.Add(itemDefinition.shortname, doorSettings);
                }
                if (doorSettings.enabled && !supportedDoors.ContainsKey(door.ShortPrefabName))
                {
                    supportedDoors.Add(door.ShortPrefabName, doorSettings.displayName);
                }
            }
            SaveConfig();
        }

        #region RustTranslationAPI

        private string GetDeployableTranslation(string language, string deployable) => (string)RustTranslationAPI.Call("GetDeployableTranslation", language, deployable);

        private string GetDeployableDisplayName(BasePlayer player, string deployable, string displayName)
        {
            if (RustTranslationAPI != null)
            {
                displayName = GetDeployableTranslation(lang.GetLanguage(player.UserIDString), deployable);
                if (!string.IsNullOrEmpty(displayName))
                {
                    return displayName;
                }
            }
            return displayName;
        }

        #endregion RustTranslationAPI

        #endregion Methods

        #region ChatCommand

        private void CmdAutoDoor(BasePlayer player, string command, string[] args)
        {
            if (configData.usePermission && !permission.UserHasPermission(player.UserIDString, PERMISSION_USE))
            {
                Print(player, Lang("NotAllowed", player.UserIDString));
                return;
            }
            var playerData = GetPlayerData(player.userID);
            if (args == null || args.Length == 0)
            {
                playerData.doorData.enabled = !playerData.doorData.enabled;
                Print(player, Lang("AutoDoor", player.UserIDString, playerData.doorData.enabled ? Lang("Enabled", player.UserIDString) : Lang("Disabled", player.UserIDString)));
                return;
            }
            float time;
            if (float.TryParse(args[0], out time))
            {
                if (time <= configData.globalS.maximumDelay && time >= configData.globalS.minimumDelay)
                {
                    playerData.doorData.time = time;
                    if (!playerData.doorData.enabled) playerData.doorData.enabled = true;
                    Print(player, Lang("AutoDoorDelay", player.UserIDString, time));
                    return;
                }
                Print(player, Lang("AutoDoorDelayLimit", player.UserIDString, configData.globalS.minimumDelay, configData.globalS.maximumDelay));
                return;
            }
            switch (args[0].ToLower())
            {
                case "a":
                case "all":
                    {
                        if (args.Length > 1)
                        {
                            if (float.TryParse(args[1], out time))
                            {
                                if (time <= configData.globalS.maximumDelay && time >= configData.globalS.minimumDelay)
                                {
                                    playerData.doorData.time = time;
                                    playerData.doorTypeS.Clear();
                                    playerData.theDoorS.Clear();
                                    Print(player, Lang("AutoDoorDelayAll", player.UserIDString, time));
                                    return;
                                }

                                Print(player,
                                    Lang("AutoDoorDelayLimit", player.UserIDString, configData.globalS.minimumDelay,
                                        configData.globalS.maximumDelay));
                                return;
                            }
                        }

                        break;
                    }
                case "s":
                case "single":
                    {
                        var door = GetLookingAtDoor(player);
                        if (door == null || door.net == null)
                        {
                            Print(player, Lang("DoorNotFound", player.UserIDString));
                            return;
                        }

                        string doorDisplayName;
                        if (!supportedDoors.TryGetValue(door.ShortPrefabName, out doorDisplayName))
                        {
                            Print(player, Lang("DoorNotSupported", player.UserIDString));
                            return;
                        }

                        StoredData.DoorData doorData;
                        if (!playerData.theDoorS.TryGetValue(door.net.ID.Value, out doorData))
                        {
                            doorData = new StoredData.DoorData
                            { enabled = true, time = configData.globalS.defaultDelay };
                            playerData.theDoorS.Add(door.net.ID.Value, doorData);
                        }

                        if (args.Length <= 1)
                        {
                            doorData.enabled = !doorData.enabled;
                            Print(player,
                                Lang("AutoDoorSingle", player.UserIDString,
                                    GetDeployableDisplayName(player, door.ShortPrefabName, doorDisplayName),
                                    doorData.enabled
                                        ? Lang("Enabled", player.UserIDString)
                                        : Lang("Disabled", player.UserIDString)));
                            return;
                        }

                        if (float.TryParse(args[1], out time))
                        {
                            if (time <= configData.globalS.maximumDelay && time >= configData.globalS.minimumDelay)
                            {
                                doorData.time = time;
                                Print(player, Lang("AutoDoorSingleDelay", player.UserIDString,
                                    GetDeployableDisplayName(player, door.ShortPrefabName, doorDisplayName), time));
                                return;
                            }

                            Print(player,
                                Lang("AutoDoorDelayLimit", player.UserIDString, configData.globalS.minimumDelay,
                                    configData.globalS.maximumDelay));
                            return;
                        }

                        break;
                    }

                case "t":
                case "type":
                    {
                        var door = GetLookingAtDoor(player);
                        if (door == null || door.net == null)
                        {
                            Print(player, Lang("DoorNotFound", player.UserIDString));
                            return;
                        }

                        string doorDisplayName;
                        if (!supportedDoors.TryGetValue(door.ShortPrefabName, out doorDisplayName))
                        {
                            Print(player, Lang("DoorNotSupported", player.UserIDString));
                            return;
                        }

                        StoredData.DoorData doorData;
                        if (!playerData.doorTypeS.TryGetValue(door.ShortPrefabName, out doorData))
                        {
                            doorData = new StoredData.DoorData
                            { enabled = true, time = configData.globalS.defaultDelay };
                            playerData.doorTypeS.Add(door.ShortPrefabName, doorData);
                        }

                        if (args.Length <= 1)
                        {
                            doorData.enabled = !doorData.enabled;
                            Print(player,
                                Lang("AutoDoorType", player.UserIDString, GetDeployableDisplayName(player, door.ShortPrefabName, doorDisplayName),
                                    doorData.enabled
                                        ? Lang("Enabled", player.UserIDString)
                                        : Lang("Disabled", player.UserIDString)));
                            return;
                        }

                        if (float.TryParse(args[1], out time))
                        {
                            if (time <= configData.globalS.maximumDelay && time >= configData.globalS.minimumDelay)
                            {
                                doorData.time = time;
                                Print(player, Lang("AutoDoorTypeDelay", player.UserIDString,
                                    GetDeployableDisplayName(player, door.ShortPrefabName, doorDisplayName), time));
                                return;
                            }

                            Print(player,
                                Lang("AutoDoorDelayLimit", player.UserIDString, configData.globalS.minimumDelay,
                                    configData.globalS.maximumDelay));
                            return;
                        }

                        break;
                    }

                case "h":
                case "help":
                    {
                        StringBuilder stringBuilder = Pool.Get<StringBuilder>();
                        stringBuilder.AppendLine();
                        var firstCmd = configData.chatS.commands[0];
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax", player.UserIDString, firstCmd));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax1", player.UserIDString, firstCmd,
                            configData.globalS.minimumDelay, configData.globalS.maximumDelay));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax2", player.UserIDString, firstCmd));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax3", player.UserIDString, firstCmd,
                            configData.globalS.minimumDelay, configData.globalS.maximumDelay));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax4", player.UserIDString, firstCmd));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax5", player.UserIDString, firstCmd,
                            configData.globalS.minimumDelay, configData.globalS.maximumDelay));
                        stringBuilder.AppendLine(Lang("AutoDoorSyntax6", player.UserIDString, firstCmd,
                            configData.globalS.minimumDelay, configData.globalS.maximumDelay));
                        Print(player, stringBuilder.ToString());
                        stringBuilder.Clear();
                        Pool.FreeUnmanaged(ref stringBuilder);
                        return;
                    }
            }
            Print(player, Lang("SyntaxError", player.UserIDString, configData.chatS.commands[0]));
        }

        #endregion ChatCommand

        #region ConfigurationFile

        private ConfigData configData;

        private class ConfigData
        {
            [JsonProperty(PropertyName = "Use permissions")]
            public bool usePermission = false;

            [JsonProperty(PropertyName = "Clear data on map wipe")]
            public bool clearDataOnWipe = false;

            [JsonProperty(PropertyName = "Global settings")]
            public GlobalSettings globalS = new GlobalSettings();

            [JsonProperty(PropertyName = "Chat settings")]
            public ChatSettings chatS = new ChatSettings();

            [JsonProperty(PropertyName = "Door Settings")]
            public Dictionary<string, DoorSettings> doorS = new Dictionary<string, DoorSettings>();

            public class DoorSettings
            {
                public bool enabled;
                public string displayName;
            }

            public class GlobalSettings
            {
                [JsonProperty(PropertyName = "Allows automatic closing of unowned doors")]
                public bool useUnownedDoor = false;

                [JsonProperty(PropertyName = "Exclude door controller")]
                public bool excludeDoorController = true;

                [JsonProperty(PropertyName = "Cancel on player dead")]
                public bool cancelOnKill = false;

                [JsonProperty(PropertyName = "Default enabled")]
                public bool defaultEnabled = true;

                [JsonProperty(PropertyName = "Default delay")]
                public float defaultDelay = 5f;

                [JsonProperty(PropertyName = "Maximum delay")]
                public float maximumDelay = 10f;

                [JsonProperty(PropertyName = "Minimum delay")]
                public float minimumDelay = 5f;
            }

            public class ChatSettings
            {
                [JsonProperty(PropertyName = "Chat command")]
                public string[] commands = { "ad", "autodoor" };

                [JsonProperty(PropertyName = "Chat prefix")]
                public string prefix = "<color=#00FFFF>[AutoDoors]</color>: ";

                [JsonProperty(PropertyName = "Chat steamID icon")]
                public ulong steamIDIcon = 0;
            }

            [JsonProperty(PropertyName = "Version")]
            public VersionNumber version;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                configData = Config.ReadObject<ConfigData>();
                if (configData == null)
                {
                    LoadDefaultConfig();
                }
                else
                {
                    UpdateConfigValues();
                }
            }
            catch (Exception ex)
            {
                PrintError($"The configuration file is corrupted. \n{ex}");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void LoadDefaultConfig()
        {
            PrintWarning("Creating a new configuration file");
            configData = new ConfigData();
            configData.version = Version;
        }

        protected override void SaveConfig() => Config.WriteObject(configData);

        private void UpdateConfigValues()
        {
            if (configData.version < Version)
            {
                if (configData.version <= default(VersionNumber))
                {
                    string prefix, prefixColor;
                    if (GetConfigValue(out prefix, "Chat Settings", "Chat Prefix") && GetConfigValue(out prefixColor, "Chat Settings", "Chat Prefix Color"))
                    {
                        configData.chatS.prefix = $"<color={prefixColor}>{prefix}</color>: ";
                    }
                }
                configData.version = Version;
            }
        }

        private bool GetConfigValue<T>(out T value, params string[] path)
        {
            var configValue = Config.Get(path);
            if (configValue == null)
            {
                value = default(T);
                return false;
            }
            value = Config.ConvertValue<T>(configValue);
            return true;
        }

        #endregion ConfigurationFile

        #region DataFile

        private StoredData storedData;

        private class StoredData
        {
            public readonly Dictionary<ulong, PlayerData> playerData = new Dictionary<ulong, PlayerData>();

            public class PlayerData
            {
                public DoorData doorData = new DoorData();
                public readonly Dictionary<ulong, DoorData> theDoorS = new Dictionary<ulong, DoorData>();
                public readonly Dictionary<string, DoorData> doorTypeS = new Dictionary<string, DoorData>();
            }

            public class DoorData
            {
                public bool enabled;
                public float time;
            }
        }

        private void LoadData()
        {
            try
            {
                storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
            }
            catch
            {
                storedData = null;
            }
            finally
            {
                if (storedData == null)
                {
                    ClearData();
                }
            }
        }

        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);

        private void ClearData()
        {
            storedData = new StoredData();
            SaveData();
        }

        private void OnNewSave(string filename)
        {
            if (configData.clearDataOnWipe)
            {
                ClearData();
            }
            else
            {
                foreach (var value in storedData.playerData.Values)
                {
                    value.theDoorS.Clear();
                }
                SaveData();
            }
        }

        #endregion DataFile

        #region LanguageFile

        private void Print(BasePlayer player, string message)
        {
            Player.Message(player, message, configData.chatS.prefix, configData.chatS.steamIDIcon);
        }

        private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NotAllowed"] = "You do not have permission to use this command",
                ["Enabled"] = "<color=#8ee700>Enabled</color>",
                ["Disabled"] = "<color=#ce422b>Disabled</color>",
                ["AutoDoor"] = "Automatic door closing is now {0}",
                ["AutoDoorDelay"] = "Automatic door closing delay set to {0}s. (Doors set by 'single' and 'type' are not included)",
                ["AutoDoorDelayAll"] = "Automatic closing delay of all doors set to {0}s",
                ["DoorNotFound"] = "You need to look at a door",
                ["DoorNotSupported"] = "This type of door is not supported",
                ["AutoDoorDelayLimit"] = "Automatic door closing delay allowed is between {0}s and {1}s",
                ["AutoDoorSingle"] = "Automatic closing of this <color=#4DFF4D>{0}</color> is {1}",
                ["AutoDoorSingleDelay"] = "Automatic closing delay of this <color=#4DFF4D>{0}</color> is {1}s",
                ["AutoDoorType"] = "Automatic closing of <color=#4DFF4D>{0}</color> door is {1}",
                ["AutoDoorTypeDelay"] = "Automatic closing delay of <color=#4DFF4D>{0}</color> door is {1}s",
                ["SyntaxError"] = "Syntax error, type '<color=#ce422b>/{0} <help | h></color>' to view help",

                ["AutoDoorSyntax"] = "<color=#ce422b>/{0} </color> - Enable/Disable automatic door closing",
                ["AutoDoorSyntax1"] = "<color=#ce422b>/{0} [time (seconds)]</color> - Set automatic closing delay for doors, the allowed time is between {1}s and {2}s. (Doors set by 'single' and 'type' are not included)",
                ["AutoDoorSyntax2"] = "<color=#ce422b>/{0} <single | s></color> - Enable/Disable automatic closing of the door you are looking at",
                ["AutoDoorSyntax3"] = "<color=#ce422b>/{0} <single | s> [time (seconds)]</color> - Set automatic closing delay for the door you are looking at, the allowed time is between {1}s and {2}s",
                ["AutoDoorSyntax4"] = "<color=#ce422b>/{0} <type | t></color> - Enable/disable automatic door closing for the type of door you are looking at. ('type' is just a word, not the type of door)",
                ["AutoDoorSyntax5"] = "<color=#ce422b>/{0} <type | t> [time (seconds)]</color> - Set automatic closing delay for the type of door you are looking at, the allowed time is between {1}s and {2}s. ('type' is just a word, not the type of door)",
                ["AutoDoorSyntax6"] = "<color=#ce422b>/{0} <all | a> [time (seconds)]</color> - Set automatic closing delay for all doors, the allowed time is between {1}s and {2}s.",
            }, this);
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["NotAllowed"] = "您没有权限使用该命令",
                ["Enabled"] = "<color=#8ee700>已启用</color>",
                ["Disabled"] = "<color=#ce422b>已禁用</color>",
                ["AutoDoor"] = "自动关门现在的状态为 {0}",
                ["AutoDoorDelay"] = "自动关门延迟设置为 {0}秒",
                ["AutoDoorDelayAll"] = "全部门的自动关闭延迟设置为 {0}秒",
                ["DoorNotFound"] = "请您看着一条门再输入指令",
                ["DoorNotSupported"] = "不支持您看着的这种门",
                ["AutoDoorDelayLimit"] = "自动关门延迟应该在 {0}秒 和 {1}秒 之间",
                ["AutoDoorSingle"] = "这条 <color=#4DFF4D>{0}</color> 的自动关闭状态为 {1}",
                ["AutoDoorSingleDelay"] = "这条 <color=#4DFF4D>{0}</color> 的自动关闭延迟为 {1}秒",
                ["AutoDoorType"] = "这种 <color=#4DFF4D>{0}</color> 的自动关闭状态为 {1}",
                ["AutoDoorTypeDelay"] = "这种 <color=#4DFF4D>{0}</color> 的自动关闭延迟为 {1}秒",
                ["SyntaxError"] = "语法错误, 输入 '<color=#ce422b>/{0} <help | h></color>' 查看帮助",

                ["AutoDoorSyntax"] = "<color=#ce422b>/{0} </color> - 启用/禁用自动关门",
                ["AutoDoorSyntax1"] = "<color=#ce422b>/{0} [时间 (秒)]</color> - 设置自动关门延迟。(时间在 {1}秒 和 {2}秒 之间) (不包括'single'和'type'设置的门)",
                ["AutoDoorSyntax2"] = "<color=#ce422b>/{0} <single | s></color> - 为您看着的这条门，启用/禁用自动关门",
                ["AutoDoorSyntax3"] = "<color=#ce422b>/{0} <single | s> [时间 (秒)]</color> - 为您看着的这条门设置自动关闭延迟。(时间在 {1}秒 和 {2}秒 之间)",
                ["AutoDoorSyntax4"] = "<color=#ce422b>/{0} <type | t></color> - 为您看着的这种门，启用/禁用自动关门",
                ["AutoDoorSyntax5"] = "<color=#ce422b>/{0} <type | t> [时间 (秒)]</color> - 为您看着的这种门设置自动关闭延迟。(时间在 {1}秒 和 {2}秒 之间)",
                ["AutoDoorSyntax6"] = "<color=#ce422b>/{0} <all | a> [时间 (秒)]</color> - 为所有门设置自动关闭延迟。(时间在 {1}秒 和 {2}秒 之间)",
            }, this, "zh-CN");
        }

        #endregion LanguageFile
    }
}