using System;

namespace InABox.Core
{
    public class UnitOfLength
    {
        public static UnitOfLength Kilometers = new UnitOfLength(1.609344);
        public static UnitOfLength NauticalMiles = new UnitOfLength(0.8684);
        public static UnitOfLength Miles = new UnitOfLength(1);

        private readonly double _fromMilesFactor;

        private UnitOfLength(double fromMilesFactor)
        {
            _fromMilesFactor = fromMilesFactor;
        }

        public double ConvertFromMiles(double input)
        {
            return input * _fromMilesFactor;
        }
    }

    public class Location : BaseObject, IEnclosedEntity
    {
        [DoubleEditor(Editable = Editable.Hidden, Visible = Visible.Optional)]
        public double Longitude { get; set; }

        [DoubleEditor(Editable = Editable.Hidden, Visible = Visible.Optional)]
        public double Latitude { get; set; }

        [DoubleEditor(Editable = Editable.Hidden, Visible = Visible.Optional)]
        public DateTime Timestamp { get; set; }

        [TextBoxEditor(Editable = Editable.Hidden, Visible = Visible.Optional)]
        public string Address { get; set; }

        public double DistanceTo(Location location, UnitOfLength unitOfLength)
        {
            var baseRad = Math.PI * Latitude / 180;
            var targetRad = Math.PI * location.Latitude / 180;
            var theta = Longitude - location.Longitude;
            var thetaRad = Math.PI * theta / 180;

            var dist =
                Math.Sin(baseRad) * Math.Sin(targetRad) + Math.Cos(baseRad) *
                Math.Cos(targetRad) * Math.Cos(thetaRad);
            dist = Math.Acos(dist);

            dist = dist * 180 / Math.PI;
            dist = dist * 60 * 1.1515;

            return unitOfLength.ConvertFromMiles(dist);
        }
    }
}