﻿//----------------------------------------------------------------------------------
// 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
{
    public abstract class VRRingBase : VRObjectGaze, IVRColored, IVRContainer
    {
        #region variables

        public static VRRingEvent OnCreated
        {
            get { if (_OnCreated == null) _OnCreated = new VRRingEvent(); return _OnCreated; }
        }
        public static VRRingEvent OnDestroyed
        {
            get { if (_OnDestroyed == null) _OnDestroyed = new VRRingEvent(); return _OnDestroyed; }
        }

        public VRRingEvent OnRingEnter, OnRingExit, OnRingTrigger;
        public VRObjectVector3Event OnLocalPositionChanged, OnLocalRotationChanged, OnLocalScaleChanged;

        public Vector3 localPosition
        {
            get { return transform.localPosition; }
            set
            {
                if (transform.localPosition != value)
                {
                    transform.localPosition = value;
                    if (OnLocalPositionChanged != null)
                        OnLocalPositionChanged.Invoke(this, value);
                }
            }
        }
        public Vector3 localRotation
        {
            get { return transform.localRotation.eulerAngles; }
            set
            {
                if (transform.localRotation.eulerAngles != value)
                {
                    transform.localRotation = Quaternion.Euler(value);
                    if (OnLocalRotationChanged != null)
                        OnLocalRotationChanged.Invoke(this, value);
                }
            }
        }
        public Vector3 localScale
        {
            get
            {
                return meshRing != null ? meshRing.transform.localScale : transform.localScale;
            }
            set
            {
                if (meshRing != null)
                {
                    if (meshRing.transform.localScale != value)
                    {
                        meshRing.transform.localScale = value;
                        if (OnLocalScaleChanged != null)
                            OnLocalScaleChanged.Invoke(this, value);
                    }
                }
                else if (transform.localScale != value)
                {
                    transform.localScale = value;
                    if (OnLocalScaleChanged != null)
                        OnLocalScaleChanged.Invoke(this, value);
                }
            }
        }

        private static VRRingEvent _OnCreated, _OnDestroyed;

        [SerializeField]
        protected MeshRenderer meshRing;
        protected float _globalAlpha = 1f;
        protected List<VRObjectGaze> _listChilds;
        protected List<IVRColored> _listChildsColored;

        #endregion


        protected override void Start()
        {
            base.Start();
            if (OnCreated != null)
                OnCreated.Invoke(this);
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            if (OnDestroyed != null)
                OnDestroyed.Invoke(this);
        }

        #region IGvrGazeResponder

        public override void OnGazeEnter()
        {
            if (OnGazeEnterEvent != null)
                OnGazeEnterEvent.Invoke(this);
            if (OnRingEnter != null)
                OnRingEnter.Invoke(this);
        }

        public override void OnGazeExit()
        {
            if (OnGazeExitEvent != null)
                OnGazeExitEvent.Invoke(this);
            if (OnRingExit != null)
                OnRingExit.Invoke(this);
        }

        public override void OnGazeTrigger()
        {
            if (OnGazeTriggerEvent != null)
                OnGazeTriggerEvent.Invoke(this);
            if (OnRingTrigger != null)
                OnRingTrigger.Invoke(this);
        }

        #endregion IGvrGazeResponder

        #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

        protected virtual IEnumerator ScaleCoroutine(float height)
        {
            if (meshRing != null)
            {
                Vector3 meshLocalScale = localScale;
                Vector3 colliderSize = collider.size;
                float lerp = 0;
                while (lerp < 1)
                {
                    lerp += 0.02f;
                    meshLocalScale.z = Mathf.Lerp(meshLocalScale.z, height, lerp);
                    localScale = meshLocalScale;
                    colliderSize.z = meshRing.bounds.size.y;
                    collider.size = colliderSize;
                    yield return new WaitForSeconds(0.02f);
                }
            }
        }
    }
}