<commit_before>﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using ProtoBuf;

namespace Oxide.Core.Libraries
{
    public class Lang : Library
    {
        #region Initialization

        public override bool IsGlobal => false;

        private const string defaultLang = "en";
        private readonly LangData langData;
        private readonly Dictionary<string, Dictionary<string, string>> langFiles;
        private readonly Dictionary<Plugin, Event.Callback<Plugin, PluginManager>> pluginRemovedFromManager;

        [ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
        private class LangData
        {
            public string Lang = defaultLang;
            public readonly Dictionary<string, string> UserData = new Dictionary<string, string>();
        }

        /// <summary>
        /// Initializes a new instance of the Lang class
        /// </summary>
        public Lang()
        {
            langFiles = new Dictionary<string, Dictionary<string, string>>();
            langData = ProtoStorage.Load<LangData>("oxide.lang") ?? new LangData();
            pluginRemovedFromManager = new Dictionary<Plugin, Event.Callback<Plugin, PluginManager>>();
        }

        #endregion

        #region Library Functions

        /// <summary>
        /// Registers a language set for a plugin
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="plugin"></param>
        /// <param name="lang"></param>
        [LibraryFunction("RegisterMessages")]
        public void RegisterMessages(Dictionary<string, string> messages, Plugin plugin, string lang = defaultLang)
        {
            if (messages == null || string.IsNullOrEmpty(lang) || plugin == null) return;

            var file = $"{lang}{Path.DirectorySeparatorChar}{plugin.Name}.json";
            var existingMessages = GetMessageFile(plugin.Name, lang);

            bool changed;
            if (existingMessages == null)
            {
                langFiles.Remove(file);
                AddLangFile(file, messages, plugin);
                changed = true;
            }
            else
            {
                changed = MergeMessages(existingMessages, messages);
                messages = existingMessages;
            }

            if (!changed) return;
            if (!Directory.Exists(Path.Combine(Interface.Oxide.LangDirectory, lang))) Directory.CreateDirectory(Path.Combine(Interface.Oxide.LangDirectory, lang));
            File.WriteAllText(Path.Combine(Interface.Oxide.LangDirectory, file), JsonConvert.SerializeObject(messages, Formatting.Indented));
        }

        /// <summary>
        /// Gets the language for a player, fall back to the default server language if no language is set
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        [LibraryFunction("GetLanguage")]
        public string GetLanguage(string userId)
        {
            string lang;
            if (!string.IsNullOrEmpty(userId) && langData.UserData.TryGetValue(userId, out lang)) return lang;
            return langData.Lang;
        }

        /// <summary>
        /// Gets all available languages for a single plugin
        /// </summary>
        /// <param name="plugin"></param>
        /// <returns></returns>
        [LibraryFunction("GetLanguages")]
        public string[] GetLanguages(Plugin plugin)
        {
            var languages = new List<string>();
            if (plugin == null) return languages.ToArray();

            foreach (var directory in Directory.GetDirectories(Interface.Oxide.LangDirectory))
            {
                if (File.Exists(Path.Combine(directory, $"{plugin.Name}.json")))
                    languages.Add(directory.Substring(Interface.Oxide.LangDirectory.Length + 1));
            }
            return languages.ToArray();
        }

        /// <summary>
        /// Gets a message for a plugin in the required language
        /// </summary>
        /// <param name="key"></param>
        /// <param name="plugin"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        [LibraryFunction("GetMessage")]
        public string GetMessage(string key, Plugin plugin, string userId = null)
        {
            if (string.IsNullOrEmpty(key) || plugin == null) return key;

            return GetMessageKey(key, plugin, GetLanguage(userId));
        }

        /// <summary>
        /// Gets all messages for a plugin in a language
        /// </summary>
        /// <returns></returns>
        [LibraryFunction("GetMessages")]
        public Dictionary<string, string> GetMessages(string lang, Plugin plugin)
        {
            if (string.IsNullOrEmpty(lang) || plugin == null) return null;

            var file = $"{lang}{Path.DirectorySeparatorChar}{plugin.Name}.json";

            Dictionary<string, string> langFile;
            if (!langFiles.TryGetValue(file, out langFile))
            {
                langFile = GetMessageFile(plugin.Name, lang);
                if (langFile == null) return null;

                AddLangFile(file, langFile, plugin);
            }
            return langFile.ToDictionary(k => k.Key, v => v.Value);
        }

        /// <summary>
        /// Gets the default language for the server
        /// </summary>
        /// <returns></returns>
        [LibraryFunction("GetServerLanguage")]
        public string GetServerLanguage() => langData.Lang;

        /// <summary>
        /// Sets the language preference for a player
        /// </summary>
        /// <param name="lang"></param>
        /// <param name="userId"></param>
        [LibraryFunction("SetLanguage")]
        public void SetLanguage(string lang, string userId)
        {
            if (string.IsNullOrEmpty(lang) || string.IsNullOrEmpty(userId)) return;

            string currentLang;
            if (langData.UserData.TryGetValue(userId, out currentLang) && lang.Equals(currentLang)) return;

            if (lang.Equals(langData.Lang)) langData.UserData.Remove(userId);
            else langData.UserData[userId] = lang;
            SaveData();
        }

        /// <summary>
        /// Sets the default language for the server
        /// </summary>
        /// <param name="lang"></param>
        [LibraryFunction("SetServerLanguage")]
        public void SetServerLanguage(string lang)<commit_msg>[Core] Remove language preference equal check<commit_after>﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using ProtoBuf;

namespace Oxide.Core.Libraries
{
    public class Lang : Library
    {
        #region Initialization

        public override bool IsGlobal => false;

        private const string defaultLang = "en";
        private readonly LangData langData;
        private readonly Dictionary<string, Dictionary<string, string>> langFiles;
        private readonly Dictionary<Plugin, Event.Callback<Plugin, PluginManager>> pluginRemovedFromManager;

        [ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
        private class LangData
        {
            public string Lang = defaultLang;
            public readonly Dictionary<string, string> UserData = new Dictionary<string, string>();
        }

        /// <summary>
        /// Initializes a new instance of the Lang class
        /// </summary>
        public Lang()
        {
            langFiles = new Dictionary<string, Dictionary<string, string>>();
            langData = ProtoStorage.Load<LangData>("oxide.lang") ?? new LangData();
            pluginRemovedFromManager = new Dictionary<Plugin, Event.Callback<Plugin, PluginManager>>();
        }

        #endregion

        #region Library Functions

        /// <summary>
        /// Registers a language set for a plugin
        /// </summary>
        /// <param name="messages"></param>
        /// <param name="plugin"></param>
        /// <param name="lang"></param>
        [LibraryFunction("RegisterMessages")]
        public void RegisterMessages(Dictionary<string, string> messages, Plugin plugin, string lang = defaultLang)
        {
            if (messages == null || string.IsNullOrEmpty(lang) || plugin == null) return;

            var file = $"{lang}{Path.DirectorySeparatorChar}{plugin.Name}.json";
            var existingMessages = GetMessageFile(plugin.Name, lang);

            bool changed;
            if (existingMessages == null)
            {
                langFiles.Remove(file);
                AddLangFile(file, messages, plugin);
                changed = true;
            }
            else
            {
                changed = MergeMessages(existingMessages, messages);
                messages = existingMessages;
            }

            if (!changed) return;
            if (!Directory.Exists(Path.Combine(Interface.Oxide.LangDirectory, lang))) Directory.CreateDirectory(Path.Combine(Interface.Oxide.LangDirectory, lang));
            File.WriteAllText(Path.Combine(Interface.Oxide.LangDirectory, file), JsonConvert.SerializeObject(messages, Formatting.Indented));
        }

        /// <summary>
        /// Gets the language for a player, fall back to the default server language if no language is set
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        [LibraryFunction("GetLanguage")]
        public string GetLanguage(string userId)
        {
            string lang;
            if (!string.IsNullOrEmpty(userId) && langData.UserData.TryGetValue(userId, out lang)) return lang;
            return langData.Lang;
        }

        /// <summary>
        /// Gets all available languages for a single plugin
        /// </summary>
        /// <param name="plugin"></param>
        /// <returns></returns>
        [LibraryFunction("GetLanguages")]
        public string[] GetLanguages(Plugin plugin)
        {
            var languages = new List<string>();
            if (plugin == null) return languages.ToArray();

            foreach (var directory in Directory.GetDirectories(Interface.Oxide.LangDirectory))
            {
                if (File.Exists(Path.Combine(directory, $"{plugin.Name}.json")))
                    languages.Add(directory.Substring(Interface.Oxide.LangDirectory.Length + 1));
            }
            return languages.ToArray();
        }

        /// <summary>
        /// Gets a message for a plugin in the required language
        /// </summary>
        /// <param name="key"></param>
        /// <param name="plugin"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        [LibraryFunction("GetMessage")]
        public string GetMessage(string key, Plugin plugin, string userId = null)
        {
            if (string.IsNullOrEmpty(key) || plugin == null) return key;

            return GetMessageKey(key, plugin, GetLanguage(userId));
        }

        /// <summary>
        /// Gets all messages for a plugin in a language
        /// </summary>
        /// <returns></returns>
        [LibraryFunction("GetMessages")]
        public Dictionary<string, string> GetMessages(string lang, Plugin plugin)
        {
            if (string.IsNullOrEmpty(lang) || plugin == null) return null;

            var file = $"{lang}{Path.DirectorySeparatorChar}{plugin.Name}.json";

            Dictionary<string, string> langFile;
            if (!langFiles.TryGetValue(file, out langFile))
            {
                langFile = GetMessageFile(plugin.Name, lang);
                if (langFile == null) return null;

                AddLangFile(file, langFile, plugin);
            }
            return langFile.ToDictionary(k => k.Key, v => v.Value);
        }

        /// <summary>
        /// Gets the default language for the server
        /// </summary>
        /// <returns></returns>
        [LibraryFunction("GetServerLanguage")]
        public string GetServerLanguage() => langData.Lang;

        /// <summary>
        /// Sets the language preference for a player
        /// </summary>
        /// <param name="lang"></param>
        /// <param name="userId"></param>
        [LibraryFunction("SetLanguage")]
        public void SetLanguage(string lang, string userId)
        {
            if (string.IsNullOrEmpty(lang) || string.IsNullOrEmpty(userId)) return;

            string currentLang;
            if (langData.UserData.TryGetValue(userId, out currentLang) && lang.Equals(currentLang)) return;

            langData.UserData[userId] = lang;
            SaveData();
        }

        /// <summary>
        /// Sets the default language for the server
        /// </summary>
        /// <param name="lang"></param>
        [LibraryFunction("SetServerLanguage")]
        public void SetServerLanguage(string lang)
{'fraction_non_alphanumeric': 0.1219436466661492, 'fraction_numerical': 0.0001552433439416285, 'mean_word_length': 2.04298535663675, 'pattern_counts': {'":': 0, '<': 133, '<?xml version=': 0, '>': 141, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4199443', 'n_tokens_mistral': 3186, 'n_tokens_neox': 3136, 'n_words': 802}