using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using JetBrains.Annotations;
using NaughtyAttributes;
using UnityEngine;

namespace EscapeRoomEngine.Desert.Runtime.Puzzle_A
{
    /// <summary>
    /// The rotating ring in the symbol ball module.
    /// </summary>
    public class Ring : MonoBehaviour
    {
        [Tooltip("Whether the ring is rotating.")]
        public bool rotating = true;
        [Tooltip("The current angle of the rotation.")]
        public float rotationAngle;
        [Tooltip("The range in degrees from the front of the module where a symbol should be lit up.")]
        [MinMaxSlider(-180, 180)]
        public Vector2 activeRange;
        [BoxGroup("Internal")] [Required]
        public Crystal crystal;
        [BoxGroup("Internal")]
        [ValidateInput("SymbolCount", "Must have same amount of symbols and slots.")]
        public List<Symbol> symbols;
        [BoxGroup("Internal")]
        public List<Transform> symbolSlots;

        private void Awake()
        {
            var angleDistance = 360f / symbols.Count;
            List<Symbol> symbolInstances = new(symbols.Count);
            
            for (var i = 0; i < symbols.Count; i++)
            {
                var symbol = Instantiate(symbols.RandomElement(), symbolSlots[i], false);
                symbol.symbolPosition = i;
                symbol.anglePosition = i * angleDistance;
                symbolInstances.Add(symbol);
            }

            symbols = symbolInstances;
        }

        private void Update()
        {
            if(rotating)
            {
                transform.localRotation = Quaternion.AngleAxis(rotationAngle, Vector3.forward);

                var activeSymbol = false;
                symbols.ForEach(symbol =>
                {
                    var angle = (rotationAngle - symbol.anglePosition) % 360;
                    var active = angle > activeRange.x && angle < activeRange.y || angle > 360 + activeRange.x;
                    symbol.Active = active;
                    activeSymbol |= active;
                });
                crystal.Active = activeSymbol;
            }
        }

        [UsedImplicitly] private bool SymbolCount(List<Symbol> list) => list.Count == symbolSlots.Count;
    }
}
