#if UNITY_5_3_OR_NEWER
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

namespace RoboidControl.Unity {

    /// <summary>
    /// The representation of a Thing in Unity
    /// </summary>
    public class Thing : MonoBehaviour {

        /// <summary>
        /// The core C# thing
        /// </summary>
        [field: SerializeField]
        public RoboidControl.Thing core { get; set; }

        private string modelUrl = null;

        /// <summary>
        /// Set the core C# thing
        /// </summary>
        protected void SetCoreThing(RoboidControl.Thing thing) {
            core = thing;
            core.component = this;

            SiteServer siteServer = FindAnyObjectByType<SiteServer>();
            if (siteServer == null) {
                Debug.LogWarning("No site server found");
                return;
            }
            siteServer.site.Add(thing);

        }

        public static Thing Create(RoboidControl.Thing core) {
            // Debug.Log("Creating new Unity thing");
            GameObject gameObj = string.IsNullOrEmpty(core.name) ?
                new("Thing") :
                new(core.name);
            Thing component = gameObj.AddComponent<Thing>();

            component.core = core;
            if (core.parent != null && core.parent.component != null)
                gameObj.transform.SetParent(core.parent.component.transform, false);

            if (core.position != null)
                gameObj.transform.localPosition = core.position.ToVector3();

            return component;
        }

        /// <summary>
        /// Update the Unity representation
        /// </summary>
        protected virtual void Update() {
            if (core == null)
                return;

            if (core.linearVelocity != null && core.linearVelocity.distance != 0) {
                Vector3 direction = Quaternion.AngleAxis(core.linearVelocity.direction.horizontal, Vector3.up) * Vector3.forward;
                this.transform.Translate(core.linearVelocity.distance * Time.deltaTime * direction, Space.Self);
            } else if (core.positionUpdated)
                this.transform.localPosition = core.position.ToVector3();
            
            if (core.angularVelocity != null && core.angularVelocity.distance != 0) {
                Vector3 angularVelocity = core.angularVelocity.ToVector3();
                Vector3 axis = core.angularVelocity.direction.ToVector3();
                this.transform.localRotation *= Quaternion.AngleAxis(core.angularVelocity.distance * Time.deltaTime, axis);
                //this.transform.localRotation *= Quaternion.Euler(angularVelocity * Time.deltaTime);
            } else if (core.orientationUpdated)
                this.transform.localRotation = core.orientation.ToQuaternion();

            if (!string.IsNullOrEmpty(core.modelUrl) && this.modelUrl == null) {
                string extension = core.modelUrl.Substring(core.modelUrl.LastIndexOf("."));
                if (extension == ".jpg" || extension == ".png") {
                    StartCoroutine(LoadJPG());
                }

                this.modelUrl = core.modelUrl;
            }
        }

        private IEnumerator LoadJPG() {
            UnityWebRequest request = UnityWebRequestTexture.GetTexture(core.modelUrl);
            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success) {
                Texture2D texture = ((DownloadHandlerTexture)request.downloadHandler).texture;
                float aspectRatio = (float)texture.width / (float)texture.height;

                GameObject modelQuad = GameObject.CreatePrimitive(PrimitiveType.Quad);
                Collider c = modelQuad.GetComponent<Collider>();
                c.enabled = false;
                Destroy(c);
                modelQuad.transform.SetParent(this.transform, false);
                modelQuad.transform.localEulerAngles = new(90, -90, 0);
                modelQuad.transform.localScale = new Vector3(aspectRatio, 1, 1) / 5;
                if (this.name == "Ant")
                    modelQuad.transform.localScale *= 2;
                Material quadMaterial = new(Shader.Find("Unlit/Transparent")) {
                    mainTexture = texture
                };
                modelQuad.GetComponent<Renderer>().material = quadMaterial;
            }
            else {
                Debug.LogError("Failed to load image: " + request.error);
            }
        }


    }

}
#endif