namespace XenseAR
{
    using Cysharp.Threading.Tasks;
    using UnityEngine;

    public class AssetbundleAnchor : BaseAnchor
    {
        [Tooltip("Tên của Bundle Object. Lấy bằng cách ấn fetch, danh sách tên hiển thị trong Asset Names, sau đó copy tên bunle")]
        [SerializeField] protected string bundleObjectName;
        bool bNeedEnable = false;
        private bool isDestroying = false;
        protected virtual void Awake()
        {

        }
        protected override void OnDestroy()
        {
            isDestroying = true;
            StopAllCoroutines();
            base.OnDestroy();
        }
        protected override void Start()
        {
            base.Start();
        }
        public override void Load(AnchoringTarget target)
        {
            this.target = target;
            bundleObjectName = target.media.name;
            base.Load(target);
#if UNITY_WEBGL
            algorithm = new AllLoadAlgorithm();
#else
            algorithm = new DistanceLoadAlgorithm(target);
#endif
        }

        public string GetMessage()
        {
            return target.message;
        }
        public override void UnLoad()
        {
            base.UnLoad();
        }

        /// <summary>
        /// Only call gltf loader one time until the content able to show
        /// </summary>
        bool downloading = false;
        bool onWaiting = false;
        protected async override void StatusUpdate()
        {
            if (target == null) return;
            if (algorithm == null) return;
            if (string.IsNullOrEmpty(target.id)) return;
            bool needEnable = algorithm.IsNeedLoad(target, transform);
            if (needEnable == true && downloading == false)
            {

                HasDispose = false;

                AssetBundleLoader loader = new AssetBundleLoader(this, target.media.url, bundleObjectName);
                onWaiting = true;

                if (State.Instance.downloadingAnchor.ContainsKey(target.media.url))
                {
                    await State.Instance.downloadingAnchor[target.media.url];
                    // var waiterTask = State.Instance.downloadingAnchor[target.media.url];
                    // await UniTask.WaitUntil(() => { return waiterTask.GetAwaiter().IsCompleted; });
                    // //State.Instance.downloadingAnchor.Remove(target.media.url);
                    // await UniTask.Delay(100);
                }

                //await State.Instance.downloadingAnchor[target.media.url];
                Debug.Log("loadbundle " + target.media.url);
                var loadingTask = loader.LoadAsync();
                State.Instance.downloadingAnchor.Add(target.media.url, loadingTask);
                await loadingTask;
                HasLoad = true;
                if (State.Instance.downloadingAnchor.ContainsKey(target.media.url))
                {
                    State.Instance.downloadingAnchor.Remove(target.media.url);
                }

                downloading = true;
                onWaiting = false;
            }
            if (isDestroying) return;
            bool needDispose = algorithm.IsNeedDispose(target, transform);
            if (needDispose)
                Dispose();
            base.StatusUpdate();
        }

        public override AnchoringMediaType GetType()
        {
            return AnchoringMediaType.Assetbundle;
        }

        private void DestroyLoadingPlaceHolder(GameObject loadingPlaceHolder)
        {
            GameObject.Destroy(loadingPlaceHolder);
        }

        private GameObject CreateLoadingPlaceHolder()
        {
            GameObject resource = Resources.Load<GameObject>(Defines.PrefabResourceURL.LoadingPlaceHolderPrefab);
            GameObject mgameObject = Instantiate<GameObject>(resource, transform);
            mgameObject.transform.localPosition = new Vector3(0, 0, 0);
            mgameObject.transform.localRotation = Quaternion.identity;
            mgameObject.transform.localScale = new Vector3(1 / transform.localScale.x, 1 / transform.localScale.y, 1 / transform.localScale.z);
            return mgameObject;
        }

        public override void Dispose()
        {
            if (HasDispose) return;
            Debug.Log("Dispose " + bundleObjectName);
            downloading = false;
            onWaiting = false;
            Animation animation = GetComponentInChildren<Animation>();
            if (animation != null)
                Destroy(animation);
            foreach (Transform child in transform)
            {
                Destroy(child.gameObject);
            }
            base.Dispose();
        }

    }
}
