using Avalonia.Notification;
using CommunityToolkit.Mvvm.ComponentModel;
using Mapsui;
using Mapsui.Projections;
using NetTopologySuite.Geometries;
using NetTopologySuite.LinearReferencing;
using pavesys_iRAP.Business;
using pavesys_iRAP.Helper;
using SharpKml.Dom;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace pavesys_iRAP.ViewModels
{
    public partial class InputCorrectionPageViewModel : ViewModelBase
    {
        [ObservableProperty]
        private INotificationMessageManager manager = new NotificationMessageManager();
        //Maps are set in the code behind of this view
        [ObservableProperty]
        private Map defaultMap;
        [ObservableProperty]
        private Map interpolatedMap;
        [ObservableProperty]
        private Map kmlMap;
        //Linestringkml is also set in the code-behind
        public NetTopologySuite.Geometries.LineString LineStringKml { get; set; }
        //Will be set in MainWindowViewModel.
        public Dictionary<(decimal, decimal), List<int>> errorDic = null;
        //Will be set in MainWindowViewModel.
        public List<LogXML> xmlLogs = new();

        public List<LogXML> xmlInterpolatedLogs = new();
        [ObservableProperty]
        private bool isNotUpdating = true;

        public InputCorrectionPageViewModel() { return; }

        public void interpolateXml()
        {
            if (errorDic is not null)
            {
                var errorsDic = errorDic.Where(list => list.Value.Count >= 2 && list.Value.Count <= ConfigManager.GetInputErrorLimit());

                //Interpolação dos pontos 

                foreach (var errorDic in errorsDic)
                {
                    if (errorDic.Value.Last() < xmlInterpolatedLogs.Count - 2)
                    {
                        int totalPoints = errorDic.Value.Count + 1;
                        var start = xmlLogs[errorDic.Value.First() - 1].LonLatGPGGA;
                        var end = xmlLogs[errorDic.Value.Last() + 2].LonLatGPGGA;
                        Coordinate[] newCoordinates = new Coordinate[totalPoints];
                        newCoordinates[0] = new((double)start.Item1, (double)start.Item2);
                        newCoordinates[totalPoints - 1] = new((double)end.Item1, (double)end.Item2);
                        for (int i = 1; i < totalPoints - 1; i++)
                        {
                            double t = (double)i / (totalPoints - 1);
                            double x = (double)start.Item1 + t * (double)(end.Item1 - start.Item1);
                            double y = (double)start.Item2 + t * (double)(end.Item2 - start.Item2);
                            newCoordinates[i] = new(x, y);
                        }

                        for (int i = 0; i < errorDic.Value.Count; i++)
                        {
                            xmlInterpolatedLogs[errorDic.Value[i] - 1].LonLatGPGGA = ((decimal)newCoordinates[i].X, (decimal)newCoordinates[i].Y);
                        }
                    }
                }
            }
        }

        //public void interpolateXml()
        //{
        //    if (errorDic is not null)
        //    {
        //        var errorsDic = errorDic.Where(list => list.Value.Count >= 2 && list.Value.Count <= ConfigManager.GetInputErrorLimit());

        //        foreach (var errorDic in errorsDic)
        //        {
        //            if (errorDic.Value.Last() < xmlInterpolatedLogs.Count - 2)
        //            {
        //                var start = xmlLogs[errorDic.Value.First() - 1].LonLatGPGGA;
        //                var end = xmlLogs[errorDic.Value.Last() + 2].LonLatGPGGA;

        //                Coordinate startCoord = new((double)start.Item1, (double)start.Item2);
        //                Coordinate endCoord = new((double)end.Item1, (double)end.Item2);

        //                var lonlatStart = SphericalMercator.ToLonLat(startCoord.X, startCoord.Y);
        //                var lonlatEnd = SphericalMercator.ToLonLat(endCoord.X, endCoord.Y);

        //                double totalDistance = pavesys_iRAP.Business.InputXML.GetVincentyDistance(lonlatStart.lat, lonlatStart.lon, lonlatEnd.lat, lonlatEnd.lon);
        //                int totalPoints = (int)Math.Ceiling(totalDistance) + 1;

        //                Coordinate[] newCoordinates = new Coordinate[totalPoints];
        //                newCoordinates[0] = startCoord;
        //                newCoordinates[totalPoints - 1] = endCoord;

        //                for (int i = 1; i < totalPoints - 1; i++)
        //                {
        //                    double t = i / (double)(totalPoints - 1);
        //                    double x = startCoord.X + t * (endCoord.X - startCoord.X);
        //                    double y = startCoord.Y + t * (endCoord.Y - startCoord.Y);
        //                    newCoordinates[i] = new(x, y);
        //                }

        //                int interpolatedIndex = 0;
        //                for (int i = errorDic.Value.First() - 1; i <= errorDic.Value.Last() + 1; i++)
        //                {
        //                    if (interpolatedIndex < totalPoints)
        //                    {
        //                        xmlInterpolatedLogs[i].LonLatGPGGA = ((decimal)newCoordinates[interpolatedIndex].X, (decimal)newCoordinates[interpolatedIndex].Y);
        //                        interpolatedIndex++;
        //                    }
        //                }
        //            }
        //        }
        //    }
        //}
        public NetTopologySuite.Geometries.LineString DensifyLineString(NetTopologySuite.Geometries.LineString lineString)
        {
            
           
            var coordinates = lineString.Coordinates;
            var densifiedCoordinates = new List<NetTopologySuite.Geometries.Coordinate>();

            for (int i = 0; i < coordinates.Length - 1; i++)
            {
                var startCoord = coordinates[i];
                var endCoord = coordinates[i + 1];

                var lonlatStart = SphericalMercator.ToLonLat(startCoord.X, startCoord.Y);
                var lonlatEnd = SphericalMercator.ToLonLat(endCoord.X, endCoord.Y);
                //var distance = startCoord.Distance(endCoord);
                var distance = pavesys_iRAP.Business.InputXML.GetVincentyDistance(lonlatStart.lat, lonlatStart.lon, lonlatEnd.lat, lonlatEnd.lon);

                if (distance > 0.01) // Ignore segments with almost zero distance
                {
                    var numPoints = (int)Math.Ceiling(distance);

                    for (int j = 0; j < numPoints; j++)
                    {
                        var t = (double)j / (numPoints - 1);
                        var x = startCoord.X + t * (endCoord.X - startCoord.X);
                        var y = startCoord.Y + t * (endCoord.Y - startCoord.Y);
                        var newCoord = new NetTopologySuite.Geometries.Coordinate(x, y);

                        if ((densifiedCoordinates.Count == 0 || !newCoord.Equals(densifiedCoordinates[densifiedCoordinates.Count - 1])) && (!double.IsNaN(newCoord.X) && !double.IsNaN(newCoord.Y)))
                        {
                            densifiedCoordinates.Add(newCoord);
                        }
                    }
                }
            }

            // Add the last coordinate if it's not a duplicate
            if (densifiedCoordinates.Count == 0 || !coordinates[coordinates.Length - 1].Equals(densifiedCoordinates[densifiedCoordinates.Count - 1]))
            {
                densifiedCoordinates.Add(coordinates[coordinates.Length - 1]);
            }
           

            return new NetTopologySuite.Geometries.LineString(densifiedCoordinates.ToArray());
            //var b = new NetTopologySuite.Geometries.LineString(densifiedCoordinates.ToArray());
            //for (int i = 0; i < b.Coordinates.Count() - 1; i++)
            //{
            //    var lonlat1 = SphericalMercator.ToLonLat(b.Coordinates[i].X, b.Coordinates[i].Y);
            //    var lonlat2 = SphericalMercator.ToLonLat(b.Coordinates[i + 1].X, b.Coordinates[i + 1].Y);
            //    Debug.WriteLine(pavesys_iRAP.Business.InputXML.GetVincentyDistance(lonlat1.lat, lonlat1.lon, lonlat2.lat, lonlat2.lon));
            //}

        }

    }
}
