using MonoGame.FourEngine.Exceptions;
using MonoGame.FourEngine.Resources;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MonoGame.FourEngine.Services
{
    public class BasicResourceManager : IResourceManager
    {
        private Dictionary<string, Dictionary<string, IResource>> _dict = new Dictionary<string, Dictionary<string, IResource>>();

        public T Get<T>(string fileName) where T : IResource
            => (T)Get(typeof(T).Name, fileName);

        public IResource Get(string typeName, string fileName)
        {
            var typeDict = GetTypeDict(typeName);
            if (!typeDict.ContainsKey(fileName))
                throw new UnknownResourceNameException(fileName);
            return typeDict[fileName];
        }

        public void Add(string typeName, IResourceDefinition arg)
        {
            var typeDict = GetTypeDict(typeName);

            if (typeDict.ContainsKey(arg.FileName))
                return;
            var type = ServiceLocator.ResourceRegistry.GetType(typeName);
            typeDict[arg.FileName] = (IResource)Activator.CreateInstance(type.AsType(), arg);
        }

        public void Clear()
        {
            foreach (var typeDict in _dict.Values)
                foreach (var pair in typeDict.ToDictionary(x => x.Key, x => x.Value))
                    if (!pair.Value.Permanent)
                    {
                        typeDict.Remove(pair.Key);
                        pair.Value.Dispose();
                    }
            GC.Collect(int.MaxValue, GCCollectionMode.Forced, true);
        }

        private Dictionary<string, IResource> GetTypeDict(string type)
        {
            if (!_dict.ContainsKey(type)) _dict.Add(type, new Dictionary<string, IResource>());
            return _dict[type];
        }
    }
}