﻿using JLGames.RocketDriver.Actions.Loaderx;
using JLGames.RocketDriver.Actions.Utils;
using JLGames.RocketDriver.CSharp.Service;
using UnityEngine;

namespace JLGames.RocketDriver.Games.Service.Preload
{
    public abstract class AbstractPreloadService : ServiceBase, IAwakableService, IProgressingService, IInitService, IPreloadService
    {
        private delegate void OnBundleLoaded();

        protected string m_SettingsName = "PreloadSettings";
        protected PreloadSettings m_Settings;
        protected readonly PreloadCache m_PreloadCache = new PreloadCache();

        private int m_Index;

        //-------------------------------------

        public bool CheckBundleConfig(string bundleName)
        {
            return m_Settings.CheckInPreloadList(bundleName);
        }

        public bool CheckBundleCached(string bundleName)
        {
            return m_PreloadCache.CheckBundleExist(bundleName);
        }

        public BundleRef GetBundle(string bundleName)
        {
            return m_PreloadCache.GetBundle(bundleName);
        }

        public void ReleaseBundle(string bundleName)
        {
            m_PreloadCache.ClearBundle(bundleName);
        }

        //IService

        public override void Clear()
        {
            m_Index = 0;
            m_PreloadCache.ClearBundles();
            base.Clear();
        }

        //IAwakableService

        public virtual void Awake()
        {
            m_Settings = Resources.Load<PreloadSettings>(m_SettingsName);
            m_ProgressingLen = (uint) m_Settings.BundleSize;
        }

        //IInitService

        public virtual void Init()
        {
            if (null == m_Settings || null == m_Settings.PreloadBundles || m_Settings.PreloadBundles.Length == 0)
            {
                InvokeInited();
                return;
            }

            if (!m_Settings.CheckValidity())
            {
                return;
            }

            DoPreloads();
        }

        private void DoPreloads()
        {
            m_Index = 0;
            LoadBundle();
        }

        private void LoadNextBundle()
        {
            m_Index += 1;
            if (m_Index >= m_Settings.BundleSize)
            {
                InvokeInited();
                return;
            }

            LoadBundle();
        }

        private void LoadBundle()
        {
            var setting = m_Settings.GetPreloadSetting(m_Index);
            LoadBundle(setting);
        }

        private void LoadBundle(PreloadBundle bundle)
        {
            Loader.LoadBundleAsync(bundle.Name, (bRef, suc) =>
            {
                if (!suc)
                {
                    DebugUtil.LogWarning($"Preload Error At: {bundle}");
                    return;
                }

                if (!bundle.AutoRelease)
                {
                    m_PreloadCache.CacheBundle(bundle.Name, bRef);
                }

                InvokdProcessing(LoadNextBundle);
//                DebugUtil.Log("LoadBundle:", bundleSetting);
            }, bundle.AutoRelease);
        }
    }
}