using System;
using System.Collections.Generic;
using UnityEngine;

public interface ILoader<T>
{
    List<T> GetList() { throw new Exception("NOT IMPLEMENT"); }
    T GetSingle() { throw new Exception("NOT IMPLEMENT"); }
}

public class DataManager : IManager
{
    private Dictionary<string, object> _cache = new Dictionary<string, object>();

    public T LoadSingle<TLoader, T>(string path) where TLoader : ILoader<T>
    {
        // 캐싱된게 있으면 그걸 반환
        if (_cache.TryGetValue(path, out object cachedItem)) return (T)cachedItem;
        // 캐싱된거 없으면 새로 로드
        TLoader load = LoadJson<TLoader, T>(path);
        // 단일 객체를 가져옴
        T single = load.GetSingle();
        
        _cache.Add(path, single);
        return single;
    }

    /// <summary>
    /// Json 파일을 로드해 TLoader 타입으로 파싱하고, 그 안의 리스트를 받아와 keySelector로 지정된 키를 기준으로 딕셔너리를 생성
    /// </summary>
    /// <typeparam name="TLoader">ILoader 를 상속받은 클래스를 넣기</typeparam>
    /// <typeparam name="TKey">키의 타입을 넣기</typeparam>
    /// <typeparam name="TValue">이것도 반환 받을 딕셔너리 안에 들어있을 값의 타입을 넣기</typeparam>
    /// <param name="path">Resources 밑에 모든 full path를 입력</param>
    /// <param name="keySelector">이거 안하면 TKey, TValue를 못찾음</param>
    public Dictionary<TKey, TValue> LoadToDict<TLoader, TKey, TValue>(string path, System.Func<TValue, TKey> keySelector) where TLoader : ILoader<TValue>
    {
        // 캐싱된게 있으면 그걸 반환
        if (_cache.TryGetValue(path, out object cachedDict)) return (Dictionary<TKey, TValue>)cachedDict;
        Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
        // 캐싱된거 없으면 새로 로드
        TLoader load = LoadJson<TLoader, TValue>(path);
        // 리스트를 받아옴
        List<TValue> list = load.GetList();
        // 리스트를 돌면서 딕셔너리에 추가
        foreach (TValue item in list) { dict.Add(keySelector(item), item); }
        
        _cache.Add(path, dict);
        return dict;
    }

    private TLoader LoadJson<TLoader, T>(string path) where TLoader : ILoader<T>
    {
        TextAsset textAsset = Manager.Resource.Load<TextAsset>($"{path}");
        TLoader data = JsonUtility.FromJson<TLoader>(textAsset.text);
        return data;
    }

    public void Clear()
    {
        _cache.Clear();
    }
}
