using NaughtyAttributes;
using Station46.Scripts;
using UnityEngine;

namespace Station46.Modules.Laser.Scripts
{
    [RequireComponent(typeof(Emission))]
    public class Laser : MonoBehaviour
    {
        private const float MaxDistance = 1000;
        
        public bool firing;
        [BoxGroup("Internal")] [SerializeField] private Transform laserStart;
        [BoxGroup("Internal")] [SerializeField] private Emission emission;
        [BoxGroup("Internal")] [SerializeField] private LineRenderer laserLineRenderer;
        
        private LaserReceiver CurrentReceiver
        {
            get => _currentReceiver;
            set
            {
                if (value == null)
                {
                    if (_currentReceiver)
                    {
                        _currentReceiver.Leave();
                    }
                    _currentReceiver = null;
                }
                else
                {
                    if (_currentReceiver)
                    {
                        _currentReceiver.Leave();
                    }
                    _currentReceiver = value;
                    _currentReceiver.Hit();
                }
            }
        }
        private LaserReceiver _currentReceiver;

        protected virtual void Start()
        {
            SetHitPosition();
        }

        protected virtual void Update()
        {
            laserLineRenderer.enabled = firing;
            emission.active = firing;

            if (firing && Physics.Raycast(
                    laserStart.position,
                    transform.TransformDirection(Vector3.forward),
                    out var hit,
                    MaxDistance, 
                    ~0,
                    QueryTriggerInteraction.Ignore
                ))
            {
                SetHitPosition(hit.distance);
                
                // check whether a receiver has been hit
                var receiver = hit.transform.GetComponent<LaserReceiver>(); // may be null
                if (receiver != CurrentReceiver)
                {
                    CurrentReceiver = receiver;
                }
            }
            else
            {
                SetHitPosition();
                
                // hitting nothing
                CurrentReceiver = null;
            }
        }

        private void SetHitPosition(float distance = MaxDistance)
        {
            laserLineRenderer.SetPosition(1, Vector3.forward * distance);
        }
    }
}
