﻿//----------------------------------------------------------------------------------
// GVRNavi | Garpix Virtual Reality Navigation
// Copyright (c) 2017 Garpix Ltd.
//
// Plugin Homepage: https://gvrnavi.garpix.com
// Author Homepage: https://garpix.com
// Support: support@garpix.com
// License: Asset Store Terms of Service and EULA
// License URI: See LICENSE file in the project root for full license information.
//----------------------------------------------------------------------------------

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace GVRNavi
{
    [RequireComponent(typeof(BoxCollider))]
    public class VRPanelGaze : VRObjectGaze, IVRColored, IVRContainer
    {
        #region variables

        public SpriteRenderer spriteRendererBackground;
        public Color colorOpened = Color.white, colorClosed = Color.white;
        public Vector2 sizeOpened = new Vector2(5f, 5f), sizeClosed = new Vector2(0f, 0f);
        public bool isShowingAtStart = false;

        public bool isShowing { get { return _isShowing; } }
        public VRTweenColor tweenColor
        {
            get
            {
                if (_tweenColor == null)
                {
                    _tweenColor = gameObject.GetComponent<VRTweenColor>();
                    if (_tweenColor == null)
                        _tweenColor = gameObject.AddComponent<VRTweenColor>();
                }
                return _tweenColor;
            }
        }

        protected VRTweenColor _tweenColor;
        protected Coroutine _coroutineScale;
        protected List<VRObjectGaze> _listChilds;
        protected List<IVRColored> _listChildsColored;
        protected float _globalAlpha = 1f;
        protected bool _isShowing = false;

        #endregion


        protected override void Start()
        {
            base.Start();
            _isShowing = isShowingAtStart;
            _globalAlpha = isShowing ? 1f : 0f;
            UpdateColor();
        }

        #region IVRContainer

        public virtual void SubscribeChild(VRObjectGaze child)
        {
            if (child == null)
                return;
            if (_listChilds == null)
                _listChilds = new List<VRObjectGaze>();
            if (_listChildsColored == null)
                _listChildsColored = new List<IVRColored>();
            if (!_listChilds.Contains(child))
                _listChilds.Add(child);
            if (child is IVRColored)
                _listChildsColored.Add(child as IVRColored);
        }

        public virtual void UnsubscribeChild(VRObjectGaze child)
        {
            if (child == null)
                return;
            if (_listChilds != null)
                _listChilds.Remove(child);
            if (child is IVRColored && _listChildsColored != null)
                _listChildsColored.Remove(child as IVRColored);
        }

        public virtual void UpdateGlobalAlphaForChilds()
        {
            float alpha = (_parentContainer != null) ? _parentContainer.GetGlobalAlpha() * _globalAlpha : _globalAlpha;
            if (_listChildsColored != null)
                foreach (var child in _listChildsColored)
                    child.SetGlobalAlpha(alpha);
        }

        public virtual float GetGlobalAlpha()
        {
            return (_parentContainer != null) ? _parentContainer.GetGlobalAlpha() * _globalAlpha : _globalAlpha;
        }

        public bool IsChild(VRObjectGaze gaze)
        {
            if (_listChilds != null)
            {
                if (_listChilds.Contains(gaze))
                    return true;
                foreach (var child in _listChilds)
                    if (child is IVRContainer)
                        if ((child as IVRContainer).IsChild(gaze))
                            return true;
            }
            return false;
        }

        #endregion IVRContainer

        #region IVRColored

        public virtual void SetGlobalAlpha(float alpha)
        {
            _globalAlpha = alpha;
            UpdateGlobalAlphaForChilds();
        }

        #endregion IVRColored

        [ContextMenu("Show")]
        public virtual void Show()
        {
            _globalAlpha = 1f;
            _isShowing = true;
            if (_coroutineScale != null)
                StopCoroutine(_coroutineScale);
            UpdateColor();
        }

        [ContextMenu("Hide")]
        public virtual void Hide()
        {
            _globalAlpha = 0f;
            _isShowing = false;
            if (_coroutineScale != null)
                StopCoroutine(_coroutineScale);
            UpdateColor();
        }

        public virtual void UpdateColor()
        {
            SetColor(isShowing ? colorOpened : colorClosed);
            if (Application.isPlaying)
            {
                SetSize(isShowing ? sizeOpened : sizeClosed);
                UpdateGlobalAlphaForChilds();
            }
            else
                SetSize(sizeOpened);
        }

        protected virtual void SetColor(Color color)
        {
            color.a *= GetGlobalAlpha();
            SetColliderEnable(color.a > 0f);
            if (spriteRendererBackground == null)
                return;
            if (Application.isPlaying)
                tweenColor.StartColoring(spriteRendererBackground.color, color, 0.2f, spriteRendererBackground);
            else
                spriteRendererBackground.color = color;
        }

        protected virtual void SetSize(Vector3 size)
        {
            if (spriteRendererBackground != null)
            {
                spriteRendererBackground.transform.localScale = size;
                float textureWidth = spriteRendererBackground.sprite.texture.width * 0.01f;
                float textureHeight = spriteRendererBackground.sprite.texture.height * 0.01f;
                collider.size = new Vector3(size.x * textureWidth, size.y * textureHeight, collider.size.z);
            }
        }

        protected virtual IEnumerator ScaleCoroutine(Vector2 size)
        {
            if (spriteRendererBackground != null)
            {
                Vector3 spriteLocalScale = spriteRendererBackground.transform.localScale;
                float textureWidth = spriteRendererBackground.sprite.texture.width * 0.01f;
                float textureHeight = spriteRendererBackground.sprite.texture.height * 0.01f;
                float lerp = 0;
                while (lerp < 1)
                {
                    yield return new WaitForSeconds(0.02f);
                    lerp = Mathf.Clamp(lerp + 0.01f + lerp * 0.05f, 0f, 1f);
                    spriteLocalScale.x = Mathf.Lerp(spriteLocalScale.x, size.x, lerp);
                    spriteLocalScale.y = Mathf.Lerp(spriteLocalScale.y, size.y, lerp);
                    spriteRendererBackground.transform.localScale = spriteLocalScale;
                    collider.size = new Vector3(spriteLocalScale.x * textureWidth, spriteLocalScale.y * textureHeight, collider.size.z);
                }
            }
        }
    }
}