using System.Collections.Generic;

using UnityEngine;
using UnityEngine.XR.ARFoundation;



#if UNITY_IOS
using System.IO;
using System.Threading.Tasks;

using UFD;

using Unity.Collections;

using UnityEngine.XR.ARKit;
#endif
using UnityEngine.XR.ARSubsystems;

namespace XenseAR
{
    public class ObjectTrackingManager : MonoBehaviour
    {
        [SerializeField] AppSettingObject appSetting;
        [SerializeField] DataScriptableObject sessionDataObject;
        [SerializeField] ARTrackedObjectManager aRTrackedObjectManager;
        [SerializeField] ARSession aRSession;

        List<string> loadedIds = new List<string>();

#if UNITY_IOS
        async void Start()
        {
            aRSession.Reset();
            XRReferenceObjectLibrary sessionXRReferenceObjects = ScriptableObject.CreateInstance<XRReferenceObjectLibrary>();
            aRTrackedObjectManager.referenceLibrary = sessionXRReferenceObjects;
            aRTrackedObjectManager.enabled = true;

            aRTrackedObjectManager.trackedObjectsChanged += trackedObjectsChanged;
            BackendServices.Instance.Post(new Proyecto26.RequestHelper()
            {
                Uri = "https://xensear.vn/dev/api/v1",
                SimpleForm = new Dictionary<string, string>()
                {
                    {"type", "GetObjectTrackingInWorld"},
                    {"blockId", appSetting.LocationSetting.blockId},
                    {"worldId", appSetting.WorldId}
                }
            }).Then((res) =>
            {
                var objectTrackingResponse = JsonUtility.FromJson<ObjectTrackingResponse>(res.Text);
                sessionDataObject.SessionData.objectTracking.targets = objectTrackingResponse.data;
                int i = 0;
                foreach (var target in sessionDataObject.SessionData.objectTracking.targets)
                {
                    target.id = (i++).ToString();
                }

                LoadObjectTrackingData(sessionDataObject.SessionData.objectTracking.targets);
            });
        }

        private void OnDestroy()
        {
            aRTrackedObjectManager.trackedObjectsChanged -= trackedObjectsChanged;
        }

        private void trackedObjectsChanged(ARTrackedObjectsChangedEventArgs obj)
        {
            foreach (var trackedobj in obj.added)
            {
                if (loadedIds.Contains(trackedobj.name)) continue;
                foreach (var trackingdata in sessionDataObject.SessionData.objectTracking.targets)
                {
                    if (trackedobj.referenceObject.name == trackingdata.id)
                    {
                        trackedobj.GetComponent<AssetbundleAnchor>().Load(trackingdata.anchoringTarget);
                        Debug.Log("trackedObjectsChanged " + trackedobj.name);
                        loadedIds.Add(trackingdata.id);
                    }
                }
            }
        }

        async Task LoadObjectTrackingData(List<ObjectTrackingData> objectTrackings)
        {
            foreach (var trackingData in objectTrackings)
            {
                string url = trackingData.arObject;
                if (string.IsNullOrEmpty(url)) continue;
                if (!url.StartsWith("http") && !url.StartsWith("streaming-assets") && !url.StartsWith("file"))
                    url = "streaming-assets://" + url;

                UnityFileDownloader ufd = new UnityFileDownloader(new string[] {
                    url,
                });
                ufd.ContinueAfterFailure = true;
                string archivePath = Path.Combine(ufd.DownloadPath, Path.GetFileName(url));
                if (File.Exists(archivePath))
                {
                }
                else
                {
                    await ufd.Download();

                }
                var arKitObject = ImportArObject(archivePath);

                if (arKitObject == null)
                {
                    Debug.Log("Reference Object Entry is null");
                    return;
                }

                var referenceObject = new XRReferenceObject(trackingData.id);
                Debug.Log("Name of reference object is : " + referenceObject.name);
                referenceObject.AddEntry(arKitObject);
                aRTrackedObjectManager.referenceLibrary.Add(referenceObject);
            }
        }

        ARKitReferenceObjectEntry ImportArObject(string filePath)
        {
            Debug.Log(filePath);
            var byteData = File.ReadAllBytes(filePath);
            var byteArr = new NativeArray<byte>(byteData, Allocator.Temp);
            var arKitObject = ARKitReferenceObjectEntry.Create(byteArr);

            //arKitObject.name = "Name";
            return arKitObject;
        }
#endif
    }
}