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

namespace BS.Shared.Core
{
    public class AbstractIDSpecificDefaultClass<T> where T : AbstractIDSpecificDefaultClass<T>, new()
    {
        #region Constants and Fields

        protected string _SpecificID = string.Empty;

        private static readonly Dictionary<string, T> _InstanceCache = new Dictionary<string, T>();

        #endregion

        #region Constructors and Destructors

        protected AbstractIDSpecificDefaultClass() {}

        #endregion

        #region Public Methods

        public static T GetInstance(string specificId, string tenant = null)
        {
	        if (specificId == null)
		        specificId = tenant;
            if (!string.IsNullOrEmpty(specificId))
            {
                if (_InstanceCache.ContainsKey(specificId))
                {
                    return _InstanceCache[specificId];
                }
                var cbSpecific = typeof(T).Assembly.GetTypes()
                    .Where(i => typeof(T).IsAssignableFrom(i))
                    .FirstOrDefault(t => t.GetCustomAttributes(typeof(IDSpecificClassAttribute), true)
                                             .ToList()
                                             .Exists(i =>
											 {
												 var attr = (IDSpecificClassAttribute)i;
												 if (attr.Identifiers != null)
													 return attr.Identifiers.Contains(specificId);
												 if (!String.IsNullOrEmpty(attr.Identifier))
													 return attr.Identifier.Equals(specificId);
												 return false;

											 }));
                if (cbSpecific != null)
                {
                    var instance = Activator.CreateInstance(cbSpecific) as T;
                    instance._SpecificID = specificId;
                    _InstanceCache.Add(specificId, instance);
                    return _InstanceCache[specificId];
                }
            }

            if (!_InstanceCache.ContainsKey(string.Empty))
            {
                _InstanceCache.Add(string.Empty, 
                                   new T
                                   {
                                       _SpecificID = specificId
                                   });
            }

            return _InstanceCache[string.Empty];
        }

        #endregion
    }
}