using System;
using RothenburgAR.Common;
using RothenburgAR.PointOfInterest;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System.Threading;

namespace RothenburgAR.UI
{
    public class DetailsPanelBehaviour : MonoBehaviour
    {
        public TextMeshProUGUI DetailsText;
        public ScrollRect DetailsTextScrollRect;
        public GameObject ModelButton;
        public PoiData SelectedPoi;

        private float initialHeight;
        private float initialWidth;

        private void Start()
        {
            DisplayManager.Instance.AddOrientationChangeListener(SetSize);
        }

        private void OnEnable()
        {
            SetSize();
        }

        private void OnDestroy()
        {
            DisplayManager.Instance.RemoveOrientationChangeListener(SetSize);
        }

        private void SetSize()
        {
            var transform = GetComponent<RectTransform>();
            var border = 0f;

            initialWidth = initialWidth == 0
                ? transform.offsetMax.x
                : initialWidth;

            initialHeight = initialHeight == 0
                ? transform.offsetMax.y
                : initialHeight;

            Debug.Log(String.Format("Recalculating DetailsPanel position. Orientation: [{1}x{2}]{0}\n", 
                Screen.orientation.ToString(), 
                Screen.currentResolution.width, 
                Screen.currentResolution.height));

            if (DisplayManager.Instance.ScreenOrientation == ScreenOrientation.Portrait)
            {
                // stretch horizontally
                transform.anchorMax = new Vector2(1, 0);
                transform.offsetMin = new Vector2(border, border);
                transform.offsetMax = new Vector2(-border, initialHeight);
            }
            else //if (Screen.orientation == ScreenOrientation.Landscape) //landscape or default?
            {
                // stretch vertically
                transform.anchorMax = new Vector2(0, 1);
                transform.offsetMin = new Vector2(border, border);
                transform.offsetMax = new Vector2(initialWidth, -border);
            }
        }

        public void DisplayModelButton(PoiData data)
        {
            if (data.HasModelDescription)
            {
                ModelButton.SetActive(true);
            }
            else
            {
                ModelButton.SetActive(false);
            }
        }

        public void SwitchToFullscreenModelView()
        {
            var viewGo = UIManager.Instance.SwitchToView(ViewName.FullscreenModelView);
            var view = viewGo.GetComponent<FullscreenModelViewBehaviour>();
            view.SetModelFromPoi(SelectedPoi);
        }

        public void SetText(TextElement el)
        {
            SetText(el.GetTextByLanguage(LanguageManager.Instance.CurrentLanguageKey));
        }

        public void SetText(String el)
        {
            DetailsText.text = el;

            // Scroll to top
            DetailsTextScrollRect.normalizedPosition = new Vector2(0, 1);
        }

        public void UpdateOpeningAnimation(Vector3 position)
        {
            float duration = .4f;
            StartCoroutine(SetSizeAfterSeconds(duration + .1f));

            var scale = DisplayManager.Instance.GetComponent<RectTransform>().localScale.x;
            Vector3 screenMiddle = new Vector3(Screen.width / scale, Screen.height / scale, 0) * 0.5f;

            Vector3 startPos = Camera.main.WorldToScreenPoint(position) / scale - screenMiddle;
            Vector3 endPos = -screenMiddle;

            float startScale = 0.05f;
            float endScale = 1;

            var anim = GetComponent<Animation>();
            var clip = new AnimationClip
            {
                legacy = true,
                name = "DetailsOpen",
            };

            // inTangent and outTangent are the curve's angles to and from this keyframe in radians.
            // outTangent for all the first keyframe of all curves are set to directly point at the second frame,
            // effectively disabling the easing and making it a linear motion.
            // beware: setters for Keyframe.inTangent and Keyframe.outTangent seem to not work.
            var curvePosX = new AnimationCurve();
            curvePosX.AddKey(new Keyframe(0f, startPos.x, 0f, (endPos.x - startPos.x) / duration));
            curvePosX.AddKey(new Keyframe(duration, endPos.x));

            var curvePosY = new AnimationCurve();
            curvePosY.AddKey(new Keyframe(0f, startPos.y, 0f, (endPos.y - startPos.y) / duration));
            curvePosY.AddKey(new Keyframe(duration, endPos.y));

            clip.SetCurve(string.Empty, typeof(Transform), "localPosition.x", curvePosX);
            clip.SetCurve(string.Empty, typeof(Transform), "localPosition.y", curvePosY);

            var curveScaleX = new AnimationCurve();
            curveScaleX.AddKey(new Keyframe(0f, startScale, 0f, (endScale - startScale) / duration));
            curveScaleX.AddKey(new Keyframe(duration, endScale));

            var curveScaleY = new AnimationCurve();
            curveScaleY.AddKey(new Keyframe(0f, startScale, 0f, (endScale - startScale) / duration));
            curveScaleY.AddKey(new Keyframe(duration, endScale));

            clip.SetCurve(string.Empty, typeof(Transform), "localScale.x", curveScaleX);
            clip.SetCurve(string.Empty, typeof(Transform), "localScale.y", curveScaleY);

            anim.AddClip(clip, clip.name);
            anim.Play(clip.name);
        }

        private IEnumerator SetSizeAfterSeconds(float duration)
        {
            yield return new WaitForSecondsRealtime(duration);
            SetSize();
        }
    }
}