using System;
using Assets.Scripts.Gameplay;
using UnityEngine;

namespace Assets.Scripts.Gearbox
{
    public class GearboxController : MonoBehaviour
    {
        private GearboxMarkers[] _markers;
        private CarController.CarController _car;         //This is ugly. Fix this 
        private Transform _shifter;
        private int _activeMarker;
        private int _targetId;
        private Vector3 _targetPosition;
        private bool _move;

        void Awake()
        {
            _markers = new GearboxMarkers[9];

            FindChildren(transform);
        }

        void FindChildren(Transform obj)
        {
            var markers = string.Equals(obj.name, "Markers", StringComparison.CurrentCultureIgnoreCase);
            var markerCount = 0;
            foreach (Transform child in obj)
            {
                if (string.Equals(child.name, "Shift", StringComparison.CurrentCultureIgnoreCase)) _shifter = child;
                if (child.childCount > 0) FindChildren(child);
                if (!markers) continue;

                _markers[markerCount] = new GearboxMarkers()
                {
                    Position = child.transform.position,
                    Marker = child.GetComponent<GearMarker>()
                };

                if (_markers[markerCount].Marker.Id == 4) _activeMarker = markerCount;
                markerCount++;
            }
        }

        public void ChangeGear(IntVector2 dir, CarController.CarController car)
        {
            _car = car;
            if (_move) return;
            var gear = _markers[_activeMarker];
            for (var i = 0; i < gear.Marker.Neighbors.Length; ++i)
            {
                if (Equals(dir, gear.Marker.Neighbors[i].Direction))
                {
                    FindTargetId(gear.Marker.Neighbors[i].Id);
                    break;
                }
            }
        }

        void FindTargetId(int id)
        {
            for (var i = 0; i < _markers.Length; ++i)
            {
                if (id != _markers[i].Marker.Id) continue;
                _targetId = i;
                _targetPosition = _markers[i].Position;
                _move = true;
                break;
            }
        }



        void Update()
        {
            if (!_move) return;
            _shifter.transform.position = Vector3.Lerp(_shifter.transform.position, _targetPosition, 0.2f);

            if (Vector3.Distance(_shifter.transform.position, _targetPosition) > 0.1f) return;
            _car.Gear = _markers[_targetId].Marker.Gear;
            _activeMarker = _markers[_targetId].Marker.Id;
            _move = false;
        }

        bool Equals(IntVector2 a, IntVector2 b)
        {
            return a.X == b.X && a.Y == b.Y;
        }

        private struct GearboxMarkers
        {
            public Vector3 Position;
            public GearMarker Marker;
        }
    }

}
