/// -----------------------------------------------------------------------------
        /// <summary>
        ///   Loads resources from file.
        /// </summary>
        /// <param name = "portalId">Portal Id.</param>
        /// <param name = "mode">Active editor mode.</param>
        /// <param name = "type">Resource being loaded (edit or default).</param>
        /// <param name="locale">The locale of the file being edited.</param>
        /// <returns></returns>
        /// <remarks>
        ///   Depending on the editor mode, resources will be overrided using default DNN schema.
        ///   "Edit" resources will only load selected file.
        ///   When loading "Default" resources (to be used on the editor as helpers) fallback resource
        ///   chain will be used in order for the editor to be able to correctly see what
        ///   is the current default value for the any key. This process depends on the current active
        ///   editor mode:
        ///   - System: when editing system base resources on en-US needs to be loaded
        ///   - Host: base en-US, and base locale especific resource
        ///   - Portal: base en-US, host override for en-US, base locale especific resource, and host override
        ///   for locale.
        /// </remarks>
        /// -----------------------------------------------------------------------------
        private Hashtable LoadFile(int portalId, LanguageResourceMode mode, string type, string locale)
        {
            string file;
            var    ht = new Hashtable();

            if (type == "Edit")
            {
                // Only load resources from the file being edited
                file = this.ResourceFile(portalId, locale, mode);
                LoadResource(ht, file);
            }
            else if (type == "Default")
            {
                // Load system default
                file = this.ResourceFile(portalId, Localization.SystemLocale, LanguageResourceMode.System);
                LoadResource(ht, file);

                if (mode == LanguageResourceMode.Host)
                {
                    // Load base file for selected locale
                    file = this.ResourceFile(portalId, locale, LanguageResourceMode.System);
                    LoadResource(ht, file);
                }
                else if (mode == LanguageResourceMode.Portal)
                {
                    //Load host override for default locale
                    file = this.ResourceFile(portalId, Localization.SystemLocale, LanguageResourceMode.Host);
                    LoadResource(ht, file);

                    if (locale != Localization.SystemLocale)
                    {
                        // Load base file for locale
                        file = this.ResourceFile(portalId, locale, LanguageResourceMode.System);
                        LoadResource(ht, file);

                        //Load host override for selected locale
                        file = this.ResourceFile(portalId, locale, LanguageResourceMode.Host);
                        LoadResource(ht, file);
                    }
                }
            }

            return(ht);
        }
        /// -----------------------------------------------------------------------------
        /// <summary>
        ///   Updates all values from the datagrid.
        /// </summary>
        /// -----------------------------------------------------------------------------
        private string SaveResourceFileFile(int portalId, LanguageResourceMode mode, string locale, IEnumerable <LocalizationEntry> entries)
        {
            var resDoc = new XmlDocument {
                XmlResolver = null
            };
            var defDoc = new XmlDocument {
                XmlResolver = null
            };

            var filename = this.ResourceFile(portalId, locale, mode);

            resDoc.Load(File.Exists(filename)
                ? filename :
                        this.ResourceFile(portalId, Localization.SystemLocale, LanguageResourceMode.System));

            defDoc.Load(this.ResourceFile(portalId, Localization.SystemLocale, LanguageResourceMode.System));

            //store all changed resources
            var changedResources = new Dictionary <string, string>();

            // only items different from default will be saved
            foreach (var entry in entries)
            {
                var resourceKey = entry.Name;
                var txtValue    = entry.NewValue;

                var node = resDoc.SelectSingleNode(GetResourceKeyXPath(resourceKey) + "/value");
                switch (mode)
                {
                case LanguageResourceMode.System:
                    // this will save all items
                    if (node == null)
                    {
                        node = AddResourceKey(resDoc, resourceKey);
                    }
                    node.InnerText = txtValue;
                    if (txtValue != entry.DefaultValue)
                    {
                        changedResources.Add(resourceKey, txtValue);
                    }
                    break;

                case LanguageResourceMode.Host:
                case LanguageResourceMode.Portal:
                    // only items different from default will be saved
                    if (txtValue != entry.DefaultValue)
                    {
                        if (node == null)
                        {
                            node = AddResourceKey(resDoc, resourceKey);
                        }
                        node.InnerText = txtValue;
                        changedResources.Add(resourceKey, txtValue);
                    }
                    else
                    {
                        // remove item = default
                        var parent = node?.ParentNode;
                        if (parent != null)
                        {
                            resDoc.SelectSingleNode("//root")?.RemoveChild(parent);
                        }
                    }
                    break;
                }
            }

            // remove obsolete keys
            var nodeLoopVariables = resDoc.SelectNodes("//root/data");

            if (nodeLoopVariables != null)
            {
                foreach (XmlNode node in nodeLoopVariables)
                {
                    if (node.Attributes != null &&
                        defDoc.SelectSingleNode(GetResourceKeyXPath(node.Attributes["name"].Value)) == null)
                    {
                        node.ParentNode?.RemoveChild(node);
                    }
                }
            }

            // remove duplicate keys
            nodeLoopVariables = resDoc.SelectNodes("//root/data");
            if (nodeLoopVariables != null)
            {
                foreach (XmlNode node in nodeLoopVariables)
                {
                    if (node.Attributes != null)
                    {
                        var xmlNodeList = resDoc.SelectNodes(GetResourceKeyXPath(node.Attributes["name"].Value));
                        if (xmlNodeList != null && xmlNodeList.Count > 1)
                        {
                            node.ParentNode?.RemoveChild(node);
                        }
                    }
                }
            }

            switch (mode)
            {
            case LanguageResourceMode.System:
                resDoc.Save(filename);
                break;

            case LanguageResourceMode.Host:
            case LanguageResourceMode.Portal:
                var xmlNodeList = resDoc.SelectNodes("//root/data");
                if (xmlNodeList != null && xmlNodeList.Count > 0)
                {
                    // there's something to save
                    resDoc.Save(filename);
                }
                else if (File.Exists(filename))
                {
                    // nothing to be saved, if file exists delete
                    File.Delete(filename);
                }
                break;
            }

            if (changedResources.Count > 0)
            {
                var values = string.Join("; ", changedResources.Select(x => x.Key + "=" + x.Value));
                var log    = new LogInfo {
                    LogTypeKey = EventLogController.EventLogType.ADMIN_ALERT.ToString()
                };
                log.LogProperties.Add(new LogDetailInfo(LocalizeString("ResourceUpdated"), this.ResourceFile(portalId, locale, mode)));
                log.LogProperties.Add(new LogDetailInfo("Updated Values", values));
                LogController.Instance.AddLog(log);
            }

            return(string.Format(LocalizeString("Updated"), this.ResourceFile(portalId, locale, mode)));
        }
 /// -----------------------------------------------------------------------------
 /// <summary>
 ///   Returns the resource file name for a given resource and language.
 /// </summary>
 /// <param name="portalId">Portal Id.</param>
 /// <param name="language">Language Name.</param>
 /// <param name = "mode">Identifies the resource being searched (System, Host, Portal).</param>
 /// <returns>Localized File Name.</returns>
 /// -----------------------------------------------------------------------------
 private string ResourceFile(int portalId, string language, LanguageResourceMode mode)
 {
     return(Localization.GetResourceFileName(this._selectedResourceFile, language, mode.ToString(), portalId));
 }