using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DALWebApi.Interfaces;
using DALWebApi.Repositories;
using Domain.Contacts;

namespace DALWebApi
{
    /// <summary>
    /// UOW, using WEB-API based repos
    /// </summary>
    public class WebApiUOW : IWebApiUOW
    {
        private readonly IDictionary<Type, Func<string, object>> _repositoryFactories;
        protected Dictionary<Type, object> Repositories { get; private set; }

        public WebApiUOW()
        {
            //list of factories for our repos
            _repositoryFactories = GetCustomFactories();
            //here we cache already created repos
            Repositories = new Dictionary<Type, object>();
        }
        public void Commit()
        {
            // hmm, do nothing?
        }

        public IContactTypeRepository ContactTypes { get { return GetWebApiRepo<IContactTypeRepository>("https://localhost:44302/api/ContactType/"); } }
        public IPersonRepository Persons { get { return GetWebApiRepo<IPersonRepository>("https://localhost:44302/api/Person/"); } }
        public IContactRepository Contacts { get { return GetWebApiRepo<IContactRepository>("https://localhost:44302/api/Contact/"); } }
        
        // calling custom repo provier
        private T GetWebApiRepo<T>(string baseUrl) where T : class
        {
            // Look for T dictionary cache under typeof(T).
            object repoObj;
            Repositories.TryGetValue(typeof(T), out repoObj);
            if (repoObj != null)
            {
                return (T)repoObj;
            }

            return MakeRepository<T>(baseUrl);
        }

        protected virtual T MakeRepository<T>(string baseUrl)
        {
            Func<string, object> factory;
            _repositoryFactories.TryGetValue(typeof(T), out factory);
            if (factory == null)
            {
                throw new NotImplementedException("No factory for repository type, " + typeof(T).FullName);
            }
            var repo = (T)factory(baseUrl);
            Repositories[typeof(T)] = repo;
            return repo;
        }

        private static IDictionary<Type, Func<string, object>> GetCustomFactories()
        {
            return new Dictionary<Type, Func<string, object>>
                {
                    {typeof(IContactRepository), baseUrl => new ContactRepository(baseUrl)},
                    {typeof(IContactTypeRepository), baseUrl => new ContactTypeRepository(baseUrl)},
                    {typeof(IPersonRepository), baseUrl => new PersonRepository(baseUrl)},
                };
        }

    }
}
