namespace XenseAR
{
    using System;
    using System.Collections.Generic;

    using UnityEngine;
    using UnityEngine.Serialization;

    [Serializable]
    public class SessionData
    {
        public string id;
        public Navigation navigation = new Navigation();
        public Anchoring anchoring = new Anchoring();
        public ObjectTracking objectTracking = new ObjectTracking();
        public List<Location> location = new List<Location>();
        
    }
    [Serializable]
    public class ObjectTracking
    {
        public List<ObjectTrackingData> targets = new List<ObjectTrackingData>();
    }
    [Serializable]
    public class ObjectTrackingData
    {
        public AnchoringTarget anchoringTarget = new AnchoringTarget();
        public string arObject = "";
        public string id = "";
    }
    [Serializable]
    public class Navigation
    {
        public string blockId = "";
        public List<NavigationMesh> meshs = new List<NavigationMesh>();
        public List<LocationInfo> locations = new List<LocationInfo>();
        public List<NavigationTarget> targets = new List<NavigationTarget>();
    }

    [Serializable]
    public class Location
    {
        public string id;
        public string name;
        public List<string> categories;
        public string address;
        public string logoUrl;
        public List<string> thumbnailUrl;
    }

    [Serializable]
    public class NavigationMesh
    {
        public string id;
        public string url;
        public string name;
        public string blockID;
        public mTransform transform = new mTransform();
    }

    [Serializable]
    public class LocationInfo
    {
        public string id = "";
        public string name = "";
        public string location;
        public string blockID;
        public string message;
        public string typeNavigate;
        public List<NavigationTarget> navigationTargets = new List<NavigationTarget>();

        public LocationInfo Clone()
        {
            LocationInfo clone = new();
            clone.id = this.id;
            clone.name = this.name;
            clone.location = this.location;
            clone.blockID = this.id;
            clone.message = this.message;
            clone.typeNavigate = this.typeNavigate;
            clone.navigationTargets = this.navigationTargets;
            return clone;
        }
    }

    [Serializable]
    public class NavigationTarget
    {
        public string id = "";
        public string name = "";
        public string locationID = "";
        public mTransform transform = new mTransform();
    }

    [Serializable]
    public class Anchoring
    {
        public string blockId = "";
        public string worldId = "";
        public string id;
        public List<AnchoringTarget> targets = new List<AnchoringTarget>();
    }

    [Serializable]
    public class AnchoringTarget
    {
        public string id;
        public AnchoringMedia media;
        [HideInInspector]
        public mTransform transform = new mTransform();
        [HideInInspector]
        public Vector3 boundSize = Vector3.one;
        [Tooltip("Animation của đối tượng, Ví dụ: đối với Gltf, ấn preview  -> đợi -> ấn fetch -> copy animation từ danh sách")]
        public string animation = "";
        [Tooltip("Check nếu đối tượng là nội dung buộc phải có, nội dung sẽ được load khi block được load. Ví dụ: occlusion, shadow,...")]
        public bool MandatoryData = false;
        [Tooltip("Tin nhắn được gửi lên webview khi đối tượng được tương tác")]
        public string message = "";
        [Tooltip("Bán kính để hiển thị đối tượng này (ra khỏi vòng tròn này , đối tượng này sẽ bị ẩn, vùng hiển thị được tính trên mặt phẳng nằm ngang)")]
        public float interestedDistance = 25;
        [Tooltip("Bán kính để giữ đối tượng này trên RAM (ra khỏi vòng tròn, đối tượng này sẽ bị xóa khỏi RAM để tránh lag)")]
        public float disposeDistance = 30;
        [Tooltip("Độ cao xa nhất đến thiết bị để hiển thị đối tượng này (ra khỏi khoảng cách này, đối tượng này sẽ bị ẩn, vùng hiển thị được tính về phía trên và phía dưới thiết bị)")]
        public float requireHeight = 3;
        [Tooltip("Bán kính để đối tượng này phát hiện thiết bị đã đến gần hoặc ra xa đối tượng")]
        public float triggerRadius = 0;
        [Tooltip("Nhóm mà đối tượng thuộc về")]
        public string group = "";
        public Text3DMedia text3d;

    }

    [Serializable]
    public class AnchoringMedia
    {
        [HideInInspector]
        public string id;
        public string name;
        [Tooltip("Phân loại đối tượng, tự động set khi add component")]
        public AnchoringMediaType Type;
        [Tooltip("Đường dẫn để down load nội dung của đối tượng")]
        public string url;
    }

    [Serializable]
    public class Text3DMedia
    {
        public string text;
        public float textSize;
        // [HideInInspector]
        public string textColor;
    }

    [Serializable]
    public enum AnchoringMediaType
    {
        Gltf,
        ParticleEffects,
        Text3D,
        Image,
        Assetbundle,
    }

    [SerializeField]
    public enum AnimationType
    {
        None,
        Teeter,
        Float
    }


    [Serializable]
    public class Position : IUnityConvertible<Vector3>
    {
        public float x = 0;
        public float y = 0;
        public float z = 0;

        public void FromUnity(Vector3 value)
        {
            x = value.x; y = value.y; z = value.z;
        }

        public Vector3 ToUnity()
        {
            return new Vector3(x, y, z);
        }
    }
    [Serializable]
    public class Orientation : IUnityConvertible<Quaternion>
    {
        public float x = 0;
        public float y = 0;
        public float z = 0;
        public float w = 1f;

        public void FromUnity(Quaternion value)
        {
            x = value.x; y = value.y; z = value.z; w = value.w;
        }

        public Quaternion ToUnity()
        {
            return new Quaternion(x, y, z, w);
        }
    }
    [Serializable]
    public class Scale : IUnityConvertible<Vector3>
    {
        public float x = 1;
        public float y = 1;
        public float z = 1;
        public void FromUnity(Vector3 value)
        {
            x = value.x; y = value.y; z = value.z;
        }

        public Vector3 ToUnity()
        {
            return new Vector3(x, y, z);
        }
    }
    [Serializable]
    public class mTransform
    {
        public Position position = new Position();
        public Orientation orientation = new Orientation();
        public Scale scale = new Scale();

        public void FromUnity(Transform value)
        {
            position.FromUnity(value.localPosition);
            orientation.FromUnity(value.localRotation);
            scale.FromUnity(value.localScale);
        }
    }

    public interface IUnityConvertible<T>
    {
        T ToUnity();
        void FromUnity(T value);
    }
}
