using PlanTempus.Core.Exceptions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PlanTempus.Core.Configurations;

namespace PlanTempus.Core.Configurations.JsonConfigProvider
{
    public static class JsonConfigExtension
    {
        /// <summary>
        /// Adds a JSON configuration source to the configuration builder.
        /// </summary>
        /// <param name="builder">The configuration builder to add to</param>
        /// <param name="configurationFilePath">Path to the JSON configuration file. Defaults to "appconfiguration.json"</param>
        /// <param name="optional">If true, the configuration file is optional. Defaults to true</param>
        /// <param name="reloadOnChange">If true, the configuration will be reloaded when the file changes. Defaults to false</param>
        /// <returns>The configuration builder</returns>
        public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string configurationFilePath = "appconfiguration.json", bool? optional = true, bool? reloadOnChange = false)
        {
            return builder.AddProvider(new JsonConfigProvider(builder, configurationFilePath, optional ?? true, reloadOnChange ?? false));
        }
    }

    public interface IHasConfigurationFilePath
    {
        string ConfigurationFilePath { get; }
    }
    public class JsonConfigProvider : IConfigurationProvider, IHasConfigurationFilePath
    {
        private readonly IConfigurationBuilder _builder;
        private readonly bool _reloadOnChange;
        JObject _configuration;
        public string ConfigurationFilePath { get; private set; }

        public JsonConfigProvider() { }

        public JsonConfigProvider(IConfigurationBuilder builder, string configurationFilePath, bool optional, bool reloadOnChange)
        {
            if (!optional && !File.Exists(configurationFilePath))
                throw new ConfigurationException($"File not found, path: {configurationFilePath}");
            if (optional && !File.Exists(configurationFilePath))
                return;

            ConfigurationFilePath = configurationFilePath;
            _builder = builder;
            _reloadOnChange = reloadOnChange;
        }

        public void Build()
        {
            using (StreamReader file = File.OpenText(ConfigurationFilePath))
            using (JsonTextReader reader = new JsonTextReader(file))
            {
                _configuration = (JObject)JToken.ReadFrom(reader);
            }
        }

        public JObject Configuration()
        {
            return _configuration;
        }
    }
}
