﻿/****************************************************************************
* Copyright 2019 Xreal Techonology Limited. All rights reserved.
*                                                                                                                                                          
* This file is part of NRSDK.                                                                                                          
*                                                                                                                                                           
* https://www.xreal.com/        
* 
*****************************************************************************/

using NRKernal.Persistence;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using Photon.Pun;
using Photon.Realtime;
using ExitGames.Client.Photon;
using System.Threading;
using System.Threading.Tasks;



namespace NRKernal.NRExamples
{
    /// <summary> A local map example. </summary>
    public class LocalMapExample : MonoBehaviour
    {
        /// <summary> The nr world anchor store. </summary>
        private NRWorldAnchorStore m_NRWorldAnchorStore;
        /// <summary> The anchor panel. </summary>
        public Transform m_AnchorPanel;
        /// <summary> Target for the anchor item. </summary>
        private Transform target;

        /// <summary> Dictionary of anchor prefabs. </summary>
        private Dictionary<string, GameObject> m_AnchorPrefabDict = new Dictionary<string, GameObject>();

        private AliyunOSSManager ossManager;
        //public FirebaseStorageManager storageManager;

        /// <summary> Starts this object. </summary>
        private void Start()
        {
            var anchorItems = FindObjectsOfType<AnchorItem>();
            foreach (var item in anchorItems)
            {
                item.OnAnchorItemClick += OnAnchorItemClick;
                m_AnchorPrefabDict.Add(item.key, item.gameObject);
            }
            m_AnchorPanel.gameObject.SetActive(false);
            m_NRWorldAnchorStore = new NRWorldAnchorStore();
            
			ossManager = AliyunOSSManager.Instance;
#if !UNITY_EDITOR
            NRSessionManager.Instance.NativeAPI.Configuration.SetTrackableAnchorEnabled(true);
#endif
        }

        /// <summary> Updates this object. </summary>
        private void Update()
        {
            if (NRInput.GetButtonDown(ControllerButton.TRIGGER) && target != null)
            {
                AddAnchor();
            }
        }

        /// <summary> Open or close anchor panel. </summary>
        public void SwitchAnchorPanel()
        {
            m_AnchorPanel.gameObject.SetActive(!m_AnchorPanel.gameObject.activeInHierarchy);
        }

        /// <summary> Executes the 'anchor item click' action. </summary>
        /// <param name="key">        The key.</param>
        /// <param name="anchorItem"> The anchor item.</param>
        private void OnAnchorItemClick(string key, GameObject anchorItem)
        {
            if (target != null)
            {
                DestroyImmediate(target.gameObject);
            }

            target = Instantiate(anchorItem).transform;
            target.parent = NRInput.AnchorsHelper.GetAnchor(ControllerAnchorEnum.RightModelAnchor);
            target.position = target.parent.transform.position + target.parent.forward;
            target.forward = target.parent.forward;
            Destroy(target.gameObject.GetComponent<BoxCollider>());

            SwitchAnchorPanel();
        }

        /// <summary> Load NRWorldAnchorStore object. </summary>
        public void Load()
        {
            if (m_NRWorldAnchorStore == null)
            {
                return;
            }
            var list = m_NRWorldAnchorStore.GetLoadableAnchorUUID();
            foreach (var item in list)
            {
                m_NRWorldAnchorStore.LoadwithUUID(item.Key, (UInt64 handle) =>
                {
                    var go = Instantiate(m_AnchorPrefabDict[item.Value]);
#if UNITY_EDITOR
                    go.transform.position = UnityEngine.Random.insideUnitSphere + Vector3.forward * 2;
#else
                    go.transform.position = Vector3.forward * 10000;
#endif
                    NRWorldAnchor anchor = go.AddComponent<NRWorldAnchor>();
                    anchor.UserDefinedKey = item.Value;
                    anchor.UUID = item.Key;
                    anchor.BindAnchor(handle);
                    go.SetActive(true);
                    NRDebugger.Info("[NRWorldAnchorStore] LoadwithUUID: {0}, UserDefinedKey: {1} Handle: {2}", item.Key, item.Value, handle);
                });
            }
        }

        /// <summary> Save anchors your add. </summary>
        public void Save()
        {
            if (m_NRWorldAnchorStore == null)
            {
                return;
            }

            m_NRWorldAnchorStore.SaveAllAnchors(success =>
            {
                if (success)
                {
                    Debug.Log("All anchors saved successfully.");
                    // 可以在此处添加保存成功后的其他代码
                }
                else
                {
                    Debug.LogError("Failed to save some or all anchors.");
                    // 可以在此处添加保存失败后的其他代码
                }
            });
        }


        /// <summary> Destroy all anchor from memory. </summary>
        public void Destroy()
        {
            if (m_NRWorldAnchorStore == null)
            {
                return;
            }
            m_NRWorldAnchorStore.Destroy();
        }

        /// <summary> Add a new anchor. </summary>
        public void AddAnchor()
        {
            if (m_NRWorldAnchorStore == null || target == null)
            {
                return;
            }

            var anchorItem = target.GetComponent<AnchorItem>();
            if (anchorItem == null)
            {
                return;
            }
            var go = Instantiate(target.gameObject);
            go.transform.position = target.position;
            go.transform.rotation = target.rotation;
            go.SetActive(true);

            string key = go.GetComponent<AnchorItem>().key;
            NRWorldAnchor anchor = go.AddComponent<NRWorldAnchor>();
            anchor.UserDefinedKey = key;
            anchor.CreateAnchor();
            DestroyImmediate(target.gameObject);
        }

        public const string CloudAnchor2ObjectFile = "cloud_anchor2object.json";
        public async Task CloudLoad(string uuid)
        {
            if (m_NRWorldAnchorStore == null)
            {
                Debug.Log("[m_NRWorldAnchorStore] is null");
                return;
            }

            // Download the cloud anchor to object dictionary from the cloud
            string path = Path.Combine(m_NRWorldAnchorStore.MapPath, CloudAnchor2ObjectFile);
            // ossManager.DownloadFile(CloudAnchor2ObjectFile, path);
			
			await ossManager.DownloadFile(CloudAnchor2ObjectFile, path);
            // await storageManager.DownloadFile(CloudAnchor2ObjectFile, path);
            // Read the dictionary from the downloaded JSON file
            Dictionary<string, string> m_Anchor2ObjectDict = new Dictionary<string, string>();
            if (File.Exists(path))
            {
                string json = File.ReadAllText(path);
                m_Anchor2ObjectDict = LitJson.JsonMapper.ToObject<Dictionary<string, string>>(json);
            }

            // Get the UserDefinedKey for the given uuid
            string UserDefinedKey;
            
            if (m_Anchor2ObjectDict.TryGetValue(uuid, out UserDefinedKey))
            {
                // Download the anchor file from the cloud
                string anchorPath = Path.Combine(m_NRWorldAnchorStore.MapPath, uuid);
                await ossManager.DownloadFile(uuid, anchorPath);
                // await storageManager.DownloadFile(uuid, anchorPath);
                Debug.Log("anchorPath: "+anchorPath);
                Debug.Log("uuid: "+uuid);
                Debug.Log("UserDefinedKey: "+UserDefinedKey);

                // Create a new dictionary for the specific UUID and Key
                Dictionary<string, string> specificAnchorDict = new Dictionary<string, string>();
                specificAnchorDict[uuid] = UserDefinedKey;

                // Save the downloaded dictionary to the NRWorldAnchorStore
                m_NRWorldAnchorStore.SetAnchor2ObjectDict(specificAnchorDict);

                // Load the anchor
                m_NRWorldAnchorStore.LoadwithUUID(uuid, (UInt64 handle) =>
                {
                    var go = Instantiate(m_AnchorPrefabDict[UserDefinedKey]);
             
        #if UNITY_EDITOR
                    go.transform.position = UnityEngine.Random.insideUnitSphere + Vector3.forward * 2;
        #else
                    go.transform.position = Vector3.forward * 10000;
        #endif
                    NRWorldAnchor anchor = go.AddComponent<NRWorldAnchor>();
                    anchor.UserDefinedKey = UserDefinedKey;
                    anchor.UUID = uuid;
                    anchor.BindAnchor(handle);
                    go.SetActive(true);

                    NRDebugger.Info("[NRWorldAnchorStore] CloudLoadwithUUID: {0}, UserDefinedKey: {1} Handle: {2}", uuid, UserDefinedKey, handle);
                });
            }
            else
            {
                Debug.LogError("No UserDefinedKey found for uuid: " + uuid);
            }
        }

        public string testuuid;
        public void TestCloudLoad()
        {
            CloudLoad(testuuid);
        }
		
		/// <summary> Erase all anchors from disk. </summary>
        public void EraseAllAnchors()
        {
            if (m_NRWorldAnchorStore == null)
            {
                return;
            }

            string path = m_NRWorldAnchorStore.MapPath;
            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);  // the second parameter is to recursively delete the folder
                Debug.Log("[LocalMapExample] Erased all anchors.");
            }
            else
            {
                Debug.Log("[LocalMapExample] No anchors found to erase.");
            }
        }
		
        
    }

    

}