using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Numerics;
using Decal.Adapter;

namespace MosswartMassacre
{
    public class Coordinates
    {
        public double NS { get; set; }   // +N  / –S
        public double EW { get; set; }   // +E  / –W
        public double Z { get; set; }

        /* -- quick helper: player’s current AC coords -- */
        public static Coordinates Me
        {
            get
            {
                Vector3 pos = Utils.GetPlayerPosition();               // world X,Y,Z
                uint land = (uint)CoreManager.Current.Actions.Landcell;

                double ew = Geometry.LandblockToEW(land, pos.X);
                double ns = Geometry.LandblockToNS(land, pos.Y);
                return new Coordinates(ew, ns, pos.Z);
            }
        }

        public uint LandBlock => Geometry.GetLandblockFromCoordinates(EW, NS);

        /* -------- parsing “33.2S 72.9E” if you ever need it -------- */

        private static readonly Regex Rx = new Regex(
            @"(?<NSval>\d{1,3}(?:\.\d{1,3})?)(?<NSchr>[ns])[, ]+(?<EWval>\d{1,3}(?:\.\d{1,3})?)(?<EWchr>[ew])",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);

        public Coordinates() { }
        public Coordinates(double ew, double ns, double z = 0) { EW = ew; NS = ns; Z = z; }

        public static Coordinates FromString(string s)
        {
            var m = Rx.Match(s);
            if (!m.Success) return null;

            double ns = double.Parse(m.Groups["NSval"].Value, CultureInfo.InvariantCulture);
            if (m.Groups["NSchr"].Value.ToLower() == "s") ns *= -1;

            double ew = double.Parse(m.Groups["EWval"].Value, CultureInfo.InvariantCulture);
            if (m.Groups["EWchr"].Value.ToLower() == "w") ew *= -1;

            return new Coordinates(ew, ns);
        }

        /* ---------------- distance helpers ---------------- */

        public double DistanceTo(Coordinates o)
        {
            double ns = (((NS * 10) + 1019.5) * 24) - (((o.NS * 10) + 1019.5) * 24);
            double ew = (((EW * 10) + 1019.5) * 24) - (((o.EW * 10) + 1019.5) * 24);
            return Math.Sqrt(ns * ns + ew * ew + Math.Pow(Z - o.Z, 2));
        }

        public double DistanceToFlat(Coordinates o)
        {
            double ns = (((NS * 10) + 1019.5) * 24) - (((o.NS * 10) + 1019.5) * 24);
            double ew = (((EW * 10) + 1019.5) * 24) - (((o.EW * 10) + 1019.5) * 24);
            return Math.Sqrt(ns * ns + ew * ew);
        }

        public override string ToString() =>
            $"{Math.Abs(NS):F2}{(NS >= 0 ? 'N' : 'S')} {Math.Abs(EW):F2}{(EW >= 0 ? 'E' : 'W')}";
    }
}
