/// <summary>
        /// Load built-in vanilla starting resource file and user-provided JSON starting gooods files located in resources\goods subfolder
        /// </summary>
        public static void Load()
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            StreamReader vanilla     = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("UCP.Startup.Resources.Goods.vanilla.json"), Encoding.UTF8);
            string       vanillaText = vanilla.ReadToEnd();

            vanilla.Close();
            Dictionary <String, Dictionary <String, Object> > vanillaConfig = serializer.Deserialize <Dictionary <String, Dictionary <String, Object> > >(vanillaText);

            if (vanillaConfig != null)
            {
                string         description = GetLocalizedDescription("UCP.vanilla", vanillaConfig);
                ResourceChange change      = new ResourceChange("UCP.vanilla", false)
                {
                    CreateResourceHeader("res_UCP.vanilla", vanillaConfig),
                };
                change.description = description;
                changes.Add(change);
            }


            if (!Directory.Exists(Path.Combine(Environment.CurrentDirectory, "resources", "goods")))
            {
                return;
            }

            foreach (string file in Directory.EnumerateFiles(Path.Combine(Environment.CurrentDirectory, "resources", "goods"), "*.json", SearchOption.TopDirectoryOnly))
            {
                StreamReader reader       = new StreamReader(new FileStream(file, FileMode.Open), Encoding.UTF8);
                string       resourceText = reader.ReadToEnd();
                reader.Close();

                Dictionary <String, Dictionary <String, Object> > resourceConfig;
                try
                {
                    resourceConfig = serializer.Deserialize <Dictionary <String, Dictionary <String, Object> > >(resourceText);
                }
                catch (Exception)
                {
                    CreateNullChange(Path.GetFileNameWithoutExtension(file), "Invalid JSON detected");
                    continue;
                }

                try
                {
                    string         description = GetLocalizedDescription(file, resourceConfig);
                    ResourceChange change      = new ResourceChange(Path.GetFileNameWithoutExtension(file), false)
                    {
                        CreateResourceHeader("res_" + Path.GetFileNameWithoutExtension(file), resourceConfig),
                    };
                    change.description = description;
                    changes.Add(change);
                }
                catch (Exception e)
                {
                    CreateNullChange(Path.GetFileNameWithoutExtension(file), e.Message);
                }
            }
        }
        private void Refresh(object s, RoutedEventArgs e, TreeView view)
        {
            String activeChange = ResourceChange.activeChange == null ? String.Empty : ResourceChange.activeChange.TitleIdent;

            for (int i = 0; i < ResourceChange.changes.Count; i++)
            {
                view.Items.Remove(ResourceChange.changes.ElementAt(i).UIElement);
                Localization.Remove(ResourceChange.changes.ElementAt(i).TitleIdent.Substring(4) + "_descr");
            }
            ResourceChange.Refresh(s, e);
            foreach (ResourceChange change in ResourceChange.changes)
            {
                change.InitUI();
                view.Items.Add(change.UIElement);
            }

            if (ResourceChange.changes.Select(x => x.TitleIdent).Contains(activeChange))
            {
                foreach (ResourceChange change in ResourceChange.changes)
                {
                    if (change.TitleIdent == activeChange)
                    {
                        change.IsChecked = true;
                    }
                }
            }
        }
        protected override void TitleBox_Unchecked(object sender, RoutedEventArgs e)
        {
            base.TitleBox_Unchecked(sender, e);

            if (activeChange == this)
            {
                activeChange = null;
            }
        }
        protected override void TitleBox_Checked(object sender, RoutedEventArgs e)
        {
            base.TitleBox_Checked(sender, e);

            if (activeChange != null)
            {
                activeChange.IsChecked = false;
            }

            activeChange = this;
        }
        static void CreateNullChange(string file, string message)
        {
            ResourceChange change = new ResourceChange(Path.GetFileNameWithoutExtension(file).Replace(" ", ""), false)
            {
                new DefaultHeader(file, true)
                {
                    new BinaryEdit("s_resource")
                    {
                        new BinSkip(0x124),
                    },
                    new BinaryEdit("s_gold")
                    {
                        new BinSkip(0x58),
                    }
                }
            };

            change.description = message;
            change.IsValid     = false;
            changes.Add(change);
        }
        public override void InitUI()
        {
            Localization.Add(this.TitleIdent + "_descr", this.description);
            base.InitUI();
            if (this.IsChecked)
            {
                activeChange = this;
            }
            ((TextBlock)this.titleBox.Content).Text = this.TitleIdent.Substring(4).StartsWith("UCP.") ? this.TitleIdent.Substring(4).Replace("UCP.", "") : this.TitleIdent.Substring(4);

            if (this.IsValid == false)
            {
                ((TextBlock)this.titleBox.Content).TextDecorations = TextDecorations.Strikethrough;
                this.titleBox.IsEnabled = false;
                this.titleBox.ToolTip   = this.description;
                ((TextBlock)this.titleBox.Content).Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0));
            }
            else
            {
                this.titleBox.IsChecked = selectedChange.Equals(this.TitleIdent);
            }
            this.titleBox.Background = this.TitleIdent.Substring(4).StartsWith("UCP.") ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Colors.Bisque);


            if (this.TitleIdent.Substring(4).StartsWith("UCP."))
            {
                Button exportButton = new Button()
                {
                    //Width = 40,
                    Height              = 20,
                    Content             = Localization.Get("ui_aicexport"),
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment   = VerticalAlignment.Bottom,
                    Margin              = new Thickness(0, 0, 5, 5),
                };
                exportButton.Click += (s, e) => this.ExportFile();
                grid.Height        += 15;
                this.grid.Children.Add(exportButton);
            }
        }
        public override void InitUI()
        {
            Localization.Add(this.TitleIdent.Substring(4) + "_descr", this.description);
            base.InitUI();
            if (this.IsChecked)
            {
                activeChange = this;
            }
            ((TextBlock)this.titleBox.Content).Text = this.TitleIdent.Substring(4);

            if (this.IsValid == false)
            {
                ((TextBlock)this.titleBox.Content).TextDecorations = TextDecorations.Strikethrough;
                this.titleBox.IsEnabled = false;
                this.titleBox.ToolTip   = this.description;
                ((TextBlock)this.titleBox.Content).Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0));
            }
            else
            {
                this.titleBox.IsChecked = selectedChange.Equals(this.TitleIdent);
            }
        }