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

namespace JLGames.RocketDriver.Actions.Audio
{
    public class AudioCache : IDisposable
    {
        internal class CacheInfo
        {
            public string Key { get; }
            public AudioClip Clip { get; }

            public CacheInfo(string key, AudioClip clip)
            {
                Key = key;
                Clip = clip;
            }
        }

        private readonly List<CacheInfo> m_Cache;
        private int m_CacheCap;

        public int CacheCap => m_CacheCap;
        public int CacheSize => m_Cache.Count;

        public AudioCache(int cacheCap)
        {
            m_CacheCap = cacheCap;
            m_Cache = new List<CacheInfo>(cacheCap);
        }

        public bool Exist(string key)
        {
            return GetAudioClip(key) != null;
        }

        public AudioClip GetAudioClip(string key)
        {
            if (m_CacheCap == 0 || m_Cache.Count == 0) return null;
            var cache = m_Cache.Find((info => info.Key == key));
            return cache?.Clip;
        }

        public void AddToCache(string key, AudioClip clip)
        {
            if (m_CacheCap == 0 || null == clip) return;
            if (Exist(key)) return;
            if (m_Cache.Count == m_CacheCap)
            {
                m_Cache.RemoveAt(0);
            }

            TryAddToCache(key, clip);
        }

        public void RemoveFromCache(string key, AudioClip clip)
        {
            if (m_CacheCap == 0 || m_Cache.Count == 0) return;
            TryRemoveFromCache(key);
        }

        public void Dispose()
        {
            m_Cache.Clear();
        }

        private void TryAddToCache(string key, AudioClip clip)
        {
            if (Exist(key))
            {
                return;
            }

            m_Cache.Add(new CacheInfo(key, clip));
        }

        private AudioClip TryRemoveFromCache(string key)
        {
            var index = m_Cache.FindIndex((info => info.Key == key));
            if (index < 0) return null;

            var cacheInfo = m_Cache[index];
            m_Cache.RemoveAt(index);
            return cacheInfo.Clip;
        }
    }
}