using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor.SceneManagement;
#endif
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Giant.Res
{
    public class BundleSceneAsyncRequest : BundleSceneRequest
    {
        private AsyncOperation _request;

        public BundleSceneAsyncRequest(string path, bool addictive)
        : base(path, addictive)
        {

        }

        public override float progress
        {
            get
            {
                if (bundle == null)
                {
                    return _request == null ? 0 : _request.progress;
                }

                var bundleProgress = bundle.progress;
                if (bundle.dependencies.Count <= 0)
                {
                    return bundleProgress * 0.7f + (_request != null ? _request.progress * 0.5f : 0);
                }
                for (int i = 0; i < bundle.dependencies.Count; i++)
                {
                    var item = bundle.dependencies[i];
                    bundleProgress += item.progress;
                }

                return bundleProgress / (bundle.dependencies.Count + 1) * 0.5f +
                    (_request != null ? _request.progress * 0.5f : 0);
            }
        }

        public override bool isDone
        {
            get
            {
                switch (loadState)
                {
                    case LoadState.Loaded:
                        return true;
                    case LoadState.LoadAssetBundle:
                        {
                            if (bundle == null || bundle.error)
                                return true;

                            for (int i = 0; i < bundle.dependencies.Count; i++)
                            {
                                var item = bundle.dependencies[i];
                                if (item.error)
                                    return true;
                            }
                            if (!bundle.isDone)
                                return false;

                            for (int i = 0; i < bundle.dependencies.Count; i++)
                            {
                                var item = bundle.dependencies[i];
                                if (!item.isDone)
                                    return false;
                            }

                            LoadSceneAsync();
                            break;
                        }
                    case LoadState.Unload:
                        break;
                    case LoadState.LoadAsset:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                if (loadState != LoadState.LoadAsset)
                    return false;
                if (_request != null && !_request.isDone)
                    return false;
                loadState = LoadState.Loaded;
                return true;
            }
        }

        private void LoadSceneAsync()
        {
            try
            {

                if (AssetsMgr.UseAssetBundle)
                {
                    _request = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
                }
                else
                {
#if UNITY_EDITOR
                    _request = EditorSceneManager.LoadSceneAsyncInPlayMode(path, new LoadSceneParameters(loadSceneMode));
#endif
                }
                if (_request != null) {
                    _request.allowSceneActivation = _allowSceneActivation;
                }
                loadState = LoadState.LoadAsset;
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                error = true;
                loadState = LoadState.Loaded;
            }
        }

        internal override void Load()
        {
            if (!string.IsNullOrEmpty(assetBundleName))
            {
                bundle = AssetsMgr.LoadBundleAsync(assetBundleName);
                loadState = LoadState.LoadAssetBundle;
            }
            else
            {
                LoadSceneAsync();
            }
        }

        internal override void Unload()
        {
            base.Unload();
            _request = null;
        }

        private bool _allowSceneActivation = true;
        public bool allowSceneActivation 
        {
            get
            {
                return _allowSceneActivation;
            }
            set { 
                _allowSceneActivation = value;
                if (_request != null) {
                    _request.allowSceneActivation = value;
                }
            }
        }
    }
}
