using System;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Parking
{
    public class Driver
    {
        public readonly int Number;
        public readonly ParkingPreference ParkingPreference;
        public readonly Size Size;
        public GameObject GameObject;
        public bool Parked;
        public int Priority;
        public bool Rejected;
        public Spot Spot;
        public DateTime[] Times;
        public int UpdateInterval;
        public Spot ReservedSpot;
        public bool Reserved;
        public TimeSpan RealArrival => Times[2].TimeOfDay;
        public TimeSpan RealDeparture => Times[3].TimeOfDay;
        public TimeSpan PlannedArrival => Times[0].TimeOfDay;
        public TimeSpan PlannedDeparture => Times[1].TimeOfDay;

        public Driver(Size size, int number, ParkingPreference parkingPreference, int priority, int updateInterval)
        {
            Size = size;
            Number = number;
            ParkingPreference = parkingPreference;
            Priority = priority;
            UpdateInterval = updateInterval;
        }

        public void Reset()
        {
            Parked = false;
            Rejected = false;
            Reserved = false;
            ReservedSpot = null;
            if (Spot != null) {
                Spot.Free = true;
                Spot.Reserved = false;
            }
    
            Spot = null;
            if (GameObject != null)
                Object.Destroy(GameObject);
        }
    }

    public class Spot : IComparable<Spot>
    {
        public bool AlignToTop = true;
        public bool Flipped;
        public bool Free = true;
        public GameObject GameObject;
        public int Lane = 0;
        public TimeSpan LastReconfiguration = TimeSpan.Zero;
        public ParkingPreference ParkingDirection = ParkingPreference.Any;
        public bool Perpendicular = true;
        public bool Reserved = false;
        public int ReservedPriority = 0;
        public Size Size;
        public Driver OccupyingDriver;

        public Spot(Size size, bool flipped)
        {
            Size = size;
            Flipped = flipped;
        }

        public Spot()
        {

        }

        public bool Vertical => Perpendicular;

        public float LowerBorder => GameObject.transform.position.y -
                                    (!Vertical ? 2.25f / 2.0f : ParkingManager.SpotHeights[(int) Size] / 2.0f);
        public float RightBorder => GameObject.transform.position.x +
                                    (Vertical ? 2.25f / 2.0f : ParkingManager.SpotHeights[(int) Size] / 2.0f);
        public float LeftBorder => GameObject.transform.position.x -
                                    (Vertical ? 2.25f / 2.0f : ParkingManager.SpotHeights[(int) Size] / 2.0f);

        public Vector3 Position
        {
            get => GameObject.transform.position;
            set => GameObject.transform.position = value;
        }
        
        public int CompareTo(Spot obj)
        {
            return Size.CompareTo(obj.Size);
        }
    }

    public enum Size
    {
        A = 0,
        B = 1,
        C = 2,
        D = 3
    }

    public enum ParkingPreference
    {
        Any = 0,
        Front = 1,
        Back = 2
    }
}