using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml.XPath;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.Skyscraper.Scraper.Storage
{
    public sealed class ScraperStorageFactoryConnectionManager
    {
        private ScraperStorageFactoryConnectionManager()
        {
	        factories = PluginManager.GetInstance().GetScraperStorageFactories();
	        if (factories.Count == 0)
	        {
		        throw new NullReferenceException("We didn't get an ScraperStorages. There's something wrong here.");
	        }
        }

        private static ScraperStorageFactoryConnectionManager _instance;

        public static ScraperStorageFactoryConnectionManager GetInstance()
        {
            if (_instance == null)
            {
                _instance = new ScraperStorageFactoryConnectionManager();
            }
            return _instance;
        }

        private ReadOnlyDictionary<ScrapeStorageFactoryIdAttribute, IScraperStorageFactory> factories;

        public ReadOnlyCollection<KeyValuePair<ScrapeStorageFactoryIdAttribute, IScraperStorageFactory>> GetKnownFactories()
        {
            ReadOnlyCollection<KeyValuePair<ScrapeStorageFactoryIdAttribute, IScraperStorageFactory>> readOnlyCollection = factories.ToList().AsReadOnly();
            return readOnlyCollection;
        }

        public static void ConfigureFactoryFromIni(KeyValuePair<ScrapeStorageFactoryIdAttribute, IScraperStorageFactory> bootingStorage, Ini ini)
        {
	        string catName = String.Format("storage{0}", bootingStorage.Key.Id);
	        PluginManager.GetInstance().AutoconfigureObject(catName, bootingStorage.Value);
        }

        public IScraperStorageFactory AutoGetDefaultFactory()
        {
	        Ini ini = PluginManager.GetInstance().Ini;
	        int factoryId = ini.ReadValue("startup", "storage", -1);
	        if (factoryId == -1)
		        throw new NoStorageFactoryConfiguredException();

	        IScraperStorageFactory result = null;
	        foreach (KeyValuePair<ScrapeStorageFactoryIdAttribute,IScraperStorageFactory> entry in GetKnownFactories())
	        {
		        if (factoryId == entry.Key.Id)
		        {
			        ConfigureFactoryFromIni(entry, ini);
			        result = entry.Value;
			        break;
		        }
	        }


	        if (result == null)
		        throw new StorageFactoryPluginNotLoadedException();
	        return result;
        }
    }

    
}
