using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Configuration;
using GreenTree.Nachtragsmanagement.Core.Configuration;
using GreenTree.Nachtragsmanagement.Core.Domain.Config;
using GreenTree.Nachtragsmanagement.Core.Data;

namespace GreenTree.Nachtragsmanagement.Services.Configuration
{
    public class ConfigurationService : IConfigurationService
    {
        #region Fields

        private readonly IRepository<ConfigItem> _configItemRepository;

        #endregion

        #region Ctor

        /// <summary>
        /// Initializes a new instance of the ConfigurationService class
        /// </summary>
        public ConfigurationService(
            IRepository<ConfigItem> configItemRepository)
        {
            _configItemRepository = configItemRepository;
        }

        #endregion

        /// <summary>
        /// Reads the current configuration from the global config
        /// </summary>
        public AppendixConfigurationSection GetCurrentConfiguration()
        {
            var config = WebConfigurationManager.OpenWebConfiguration("~/");
            var sectionGroup = config.GetSectionGroup("appendixSectionGroup");
            var section = sectionGroup.Sections["appendixConfigSection"];

            return (AppendixConfigurationSection)section;
        }

        #region ConfigItem

        /// <summary>
        /// Gets all configItems
        /// </summary>
        public IList<ConfigItem> GetAllConfigItems()
        {
            return _configItemRepository.Table.ToList();
        }

        /// <summary>
        /// Gets a configItem by specified Id
        /// </summary>
        /// <param name="id">ConfigItem identifier.</param>
        public ConfigItem GetConfigItemById(int id)
        {
            return _configItemRepository.GetById(id);
        }

        /// <summary>
        /// Gets a configItem by specified name
        /// </summary>
        /// <param name="name">ConfigItem name.</param>
        public ConfigItem GetConfigItemByName(string name)
        {
            return _configItemRepository.Table
                .FirstOrDefault(r => r.Name == name);
        }

        /// <summary>
        /// Gets all configItems to the specified ids
        /// </summary>
        public IList<ConfigItem> GetConfigItemsByIds(int[] ids)
        {
            return _configItemRepository.Table
                .Where(r => ids.Contains(r.Id))
                .ToList();
        }

        /// <summary>
        /// Insert a configItem
        /// </summary>
        /// <param name="configItem">ConfigItem.</param>
        public void InsertConfigItem(ConfigItem configItem)
        {
            _configItemRepository.Insert(configItem);
        }

        /// <summary>
        /// Update a configItem
        /// </summary>
        /// <param name="configItem">ConfigItem.</param>
        public void UpdateConfigItem(ConfigItem configItem)
        {
            _configItemRepository.Update(configItem);
        }

        /// <summary>
        /// Delete a configItem
        /// </summary>
        /// <param name="configItem">ConfigItem.</param>
        public void DeleteConfigItem(ConfigItem configItem)
        {
            _configItemRepository.Delete(configItem);
        }

        #endregion

        #region Casting

        /// <summary>
        /// Trys to convert the config items value type and returns its actual value, otherwise NULL
        /// </summary>
        /// <typeparam name="T">The actual type.</typeparam>
        /// <param name="configItem">ConfigItem.</param>
        /// <param name="defaultValue">Value, when conversion fails.</param>
        public T TryGetConfigItemValue<T>(ConfigItem configItem, T defaultValue)
        {
            if (configItem == null)
                return defaultValue;

            object result = null;

            try
            {
                result = Convert.ChangeType(configItem.Value, typeof(T));
            }
            catch
            {
                result = defaultValue;
            }

            return (T)result;
        }

        /// <summary>
        /// Trys to convert the config items value type and returns its actual value, otherwise NULL
        /// </summary>
        /// <typeparam name="T">The actual type.</typeparam>
        /// <param name="configItemName">ConfigItem name.</param>
        /// <param name="defaultValue">Value, when conversion fails.</param>
        public T TryGetConfigItemValue<T>(string configItemName, T defaultValue)
        {
            if (String.IsNullOrEmpty(configItemName))
                return defaultValue;

            var configItem = GetConfigItemByName(configItemName);

            return TryGetConfigItemValue(configItem, defaultValue);
        }

        #endregion
    }
}
