using System.Collections.Generic;
using System.Linq;
using VCommon.Collections;

namespace VCommon.VApplication.Setting
{
    public interface ISettingProvider
    {
        IReadOnlyDictionary<string, SettingDefinition> Settings { get; }

        ReadOnlyHashSet<string> ApplicationScopeNames { get; }
        ReadOnlyHashSet<string> TenantScopeNames { get; }
        ReadOnlyHashSet<string> UserScopeNames { get; }
        ReadOnlyHashSet<string> ScriptWritableNames { get; }

        IReadOnlyCollection<string> ScriptOutputNames { get; }
        IReadOnlyCollection<string> ApplicationScriptOutputNames { get; }
    }

    public abstract class SettingProviderBase : ISettingProvider
    {
        public IReadOnlyDictionary<string, SettingDefinition> Settings { get; }

        public ReadOnlyHashSet<string> ApplicationScopeNames { get; }
        public ReadOnlyHashSet<string> TenantScopeNames { get; }
        public ReadOnlyHashSet<string> UserScopeNames { get; }
        public ReadOnlyHashSet<string> ScriptWritableNames { get; }

        public IReadOnlyCollection<string> ScriptOutputNames { get; }
        public IReadOnlyCollection<string> ApplicationScriptOutputNames { get; }

        protected SettingProviderBase()
        {
            Settings = Init();

            var settingDefinitions = Settings.Values.ToArray();

            ApplicationScopeNames = settingDefinitions.Where(p => p.Scope == SettingScope.Application).Select(p => p.Name).ToHashSet();
            TenantScopeNames = settingDefinitions.Where(p => p.Scope == SettingScope.Tenant).Select(p => p.Name).ToHashSet();
            UserScopeNames = settingDefinitions.Where(p => p.Scope == SettingScope.User).Select(p => p.Name).ToHashSet();
            ScriptOutputNames = settingDefinitions.Where(p => p.ScriptAccess != SettingScriptAccess.None).Select(p => p.Name).ToArray();
            ScriptWritableNames = settingDefinitions.Where(p => p.ScriptAccess == SettingScriptAccess.ReadWrite).Select(p => p.Name).ToHashSet();
            ApplicationScriptOutputNames = settingDefinitions.Where(p => p.Scope == SettingScope.Application && p.ScriptAccess != SettingScriptAccess.None).Select(p => p.Name).ToArray();
        }

        protected abstract IReadOnlyDictionary<string, SettingDefinition> Init();
    }
}