using NetEscapades.Configuration.Yaml;

using YamlDotNet.Core;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;

namespace OptionStudy.UnitApp
{

    /// <summary>
    /// 从文件中读取配置
    /// </summary>
    public class LoadConfigFileTest : IDisposable
    {

        private readonly ITestOutputHelper? testOutput;
        public LoadConfigFileTest(ITestOutputHelperAccessor helperAccessor)
        {
            testOutput = helperAccessor.Output;
        }

        /// <summary>
        /// 读取Json配置文件
        /// </summary>
        [Fact]
        public void ReadJsonFile_Test()
        {

            var config = new ConfigurationBuilder()
                .AddJsonFile("Configs/appsettings.json", true, true)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("JsonAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("json@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("json", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 json 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取Json配置流
        /// </summary>
        [Fact]
        public void ReadJsonStreamFile_Test()
        {
            var configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs/appsettings.json");
            var fileStream = File.OpenRead(configFilePath);

            var config = new ConfigurationBuilder()
                .AddJsonStream(fileStream)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("JsonAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("json@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("json", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 json 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取xml配置文件
        /// </summary>
        [Fact]
        public void ReadXmlFile_Test()
        {

            var config = new ConfigurationBuilder()
                .AddXmlFile("Configs/appsettings.xml", true, true)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("XmlAppName", appOption.AppName);
            Assert.Equal("1.2.3.4", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("xml@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("xml", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 xml 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取xml配置流
        /// </summary>
        [Fact]
        public void ReadXmlStreamFile_Test()
        {
            var configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs/appsettings.xml");
            var fileStream = File.OpenRead(configFilePath);

            var config = new ConfigurationBuilder()
                .AddXmlStream(fileStream)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("XmlAppName", appOption.AppName);
            Assert.Equal("1.2.3.4", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("xml@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("xml", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 xml 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取ini配置文件
        /// </summary>
        [Fact]
        public void ReadIniFile_Test()
        {

            var config = new ConfigurationBuilder()
                .AddIniFile("Configs/appsettings.ini", true, true)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("IniAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("ini@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("ini", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 ini 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取ini配置流
        /// </summary>
        [Fact]
        public void ReadIniStreamFile_Test()
        {
            var configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs/appsettings.ini");
            var fileStream = File.OpenRead(configFilePath);

            var config = new ConfigurationBuilder()
                .AddIniStream(fileStream)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("IniAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("ini@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("ini", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 ini 文件中读取配置文件!");
        }

        /// <summary>
        /// 读取Yaml配置文件
        /// 注意:需引用第三方包(微软没有开发) NetEscapades.Configuration.Yaml
        /// </summary>
        [Fact]
        public void ReadYamlFile_Test()
        {
            var config = new ConfigurationBuilder()
                .AddYamlFile("Configs/appsettings.yml", true, true)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("YamlAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("yaml@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("yaml", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 yaml 文件中读取配置文件! ");
        }

        /// <summary>
        /// 读取Yaml配置流
        /// 参阅 YamlFileParser.cs 扩展了 NetEscapades.Configuration.Yaml 库
        /// </summary>
        [Fact]
        public void ReadYamlStreamFile_Test()
        {
            var configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs/appsettings.yml");
            var fileStream = File.OpenRead(configFilePath);

            var config = new ConfigurationBuilder()
                .AddYamlStreamFile(fileStream)
                .Build();

            var appOption = config.Get<AppOption>();

            //断言
            Assert.NotNull(appOption);
            Assert.Equal("YamlAppName", appOption.AppName);
            Assert.Equal("0.0.0.1", appOption.AppVersion);

            //子配置节:父配置对象的属性名必须和配置KEY保持一致,否则不能自动绑定。
            Assert.NotNull(appOption.EMail);
            Assert.Equal("yaml@163.com", appOption.EMail.ReceiveAddress);
            Assert.Equal("yaml", appOption.EMail.Recipient);

            testOutput?.WriteLine("从 yaml 文件中读取配置文件! ");
        }

        /// <summary>
        /// 读取自定义配置文件
        /// 需要自己实现相关类库,稍后实现
        /// </summary>
        [Fact(Skip = "需要自己实现相关类库,稍后实现")]
        public void ReadCustomFile_Test()
        {

        }

        public void Dispose()
        {

        }
    }
}