using ESRI.ArcGIS.SystemUI;
using NetTopologySuite.Geometries;
using NetTopologySuite.Index.Strtree;
using NetTopologySuite.Operation.Overlay.Snap;
using NetTopologySuite.Operation.Union;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Kingo.PluginServiceInterface.Helper
{
    /// 
    /// 边界吸附处理器
    /// 
    public static class BoundarySnapper
    {
        /// 
        /// 执行边界吸附操作
        /// 
        /// 输入图斑集合
        /// 吸附容差(单位与坐标一致)
        /// 修复后的图斑集合
        public static List SnapBoundaries(List inputParcels, double tolerance = 0.001)
        {
            // 创建空间索引加速邻近查询
            var spatialIndex = new STRtree();
            foreach (var parcel in inputParcels)
            {
                spatialIndex.Insert(parcel.EnvelopeInternal, parcel);
            }
            spatialIndex.Build();
            // 复制输入数据以避免修改原始集合
            var outputParcels = new List(inputParcels);
            // 遍历每个图斑进行边界吸附
            foreach (var currentParcel in inputParcels)
            {
                // 查询可能与当前图斑相邻的图斑
                var nearbyCandidates = spatialIndex.Query(currentParcel.EnvelopeInternal);
                // 过滤出实际接触的相邻图斑
                var neighbors = nearbyCandidates
                    .Where(p => p != currentParcel && p.Touches(currentParcel))
                    .ToList();
                foreach (var neighbor in neighbors)
                {
                    // 使用NTS的GeometrySnapper执行吸附操作
                    var snapper = new GeometrySnapper(currentParcel);
                    Geometry snappedGeometry = (Geometry)snapper.SnapTo(neighbor, tolerance);
                    // 如果几何体发生改变,则更新结果集
                    if (!snappedGeometry.EqualsExact(currentParcel))
                    {
                        outputParcels.Remove(currentParcel);
                        outputParcels.Add(snappedGeometry);
                        break; // 处理第一个匹配的邻居后跳出循环
                    }
                }
            }
            return outputParcels;
        }
    }
    /// 
    /// 国土变更调查拓扑修复工具
    /// 功能:边界对齐 + 重叠消除 + 拓扑验证
    /// 
    public class TopologyRepairEngine
    {
        #region 公开接口
        /// 
        /// 执行完整拓扑修复流程
        /// 
        /// 输入图斑集合
        /// 拓扑容差(单位与坐标系一致)
        /// 最大修复迭代次数
        /// 修复后的拓扑一致图斑集合
        public static List FullRepair(List inputGeometries, double tolerance = 0.001, int maxIterations = 10)
        {
            // 阶段1:边界对齐处理
            var snapped = SnapBoundaries(inputGeometries, tolerance, maxIterations);
            // 阶段2:全局重叠消除
            var cleaned = ResolveOverlaps(snapped, tolerance);
            //// 阶段3:最终验证
            //if (!ValidateTopology(cleaned, tolerance))
            //    throw new TopologyException("拓扑修复失败,存在未解决的拓扑错误");
            return cleaned;
        }
        #endregion
        #region 核心算法
        /// 
        /// 多轮次边界吸附处理
        /// 
        private static List SnapBoundaries(List input, double tolerance, int maxIterations)
        {
            List workingSet = input.Select(g => (Geometry)g.Copy()).ToList();
            bool hasChanges;
            int iteration = 0;
            do
            {
                hasChanges = false;
                var spatialIndex = BuildSTRTree(workingSet);
                var nextGeneration = new List();
                foreach (var current in workingSet)
                {
                    var neighbors = spatialIndex.Query(current.EnvelopeInternal)
                        .Where(g => g != current && g.Touches(current))
                        .ToList();
                    Geometry processed = current;
                    foreach (var neighbor in neighbors)
                    {
                        var snapper = new GeometrySnapper(processed);
                        Geometry snapped = (Geometry)snapper.SnapTo(neighbor, CalculateDynamicTolerance(tolerance, iteration));
                        if (!snapped.EqualsTopologically(processed))
                        {
                            processed = ValidateGeometry(snapped);
                            hasChanges = true;
                            break; // 单次只处理一个邻居
                        }
                    }
                    nextGeneration.Add(processed);
                }
                workingSet = nextGeneration;
                iteration++;
            } while (hasChanges && iteration < maxIterations);
            return workingSet;
        }
        /// 
        /// 全局重叠消除处理
        /// 
        private static List ResolveOverlaps(List geometries, double tolerance)
        {
            var overlaps = DetectOverlaps(geometries, tolerance);
            if (overlaps.Count == 0) return geometries;
            var validOverlaps = overlaps
                                .Where(g => g is Polygon&&!g.IsEmpty) // 仅保留多边形
                                .Where(g => g.IsValid)// 检查有效性
                                .Cast()
                                .ToList();
            var union = CascadedPolygonUnion.Union(validOverlaps);
            if(union==null) return geometries;
            var result = new List();
            foreach (var geom in geometries)
            {
                if (geom.Intersects(union))
                {
                    var diff = geom.Difference(union);
                    result.AddRange(ExtractValidPolygons((Geometry)diff));
                }
                else
                {
                    result.Add(geom);
                }
            }
            // 递归处理残留重叠
            return ResolveOverlaps(result, tolerance); // 收紧容差
        }
        #endregion
        #region 辅助方法
        /// 
        /// 构建空间索引
        /// 
        private static STRtree BuildSTRTree(IEnumerable geometries)
        {
            var tree = new STRtree();
            foreach (var g in geometries) tree.Insert(g.EnvelopeInternal, g);
            tree.Build();
            return tree;
        }
        /// 
        /// 动态容差计算(随迭代次数衰减)
        /// 
        private static double CalculateDynamicTolerance(double baseTolerance, int iteration)
            => baseTolerance * Math.Pow(0.9, iteration);
        /// 
        /// 几何体有效性检查与修复
        /// 
        private static Geometry ValidateGeometry(Geometry geom)
        {
            if (!geom.IsValid)
            {
                // 使用缓冲区法修复常见错误
                var buffered = geom.Buffer(0);
                return buffered.IsEmpty ? (Geometry)geom : (Geometry)buffered;
            }
            return geom;
        }
        /// 
        /// 检测所有重叠区域
        /// 
        private static List DetectOverlaps(List geometries, double minArea)
        {
            var overlaps = new List();
            var index = BuildSTRTree(geometries);
            foreach (var geom in geometries)
            {
                foreach (var other in index.Query(geom.EnvelopeInternal)
                    .Where(g => g != geom && g.Intersects(geom)))
                {
                    var overlap = geom.Intersection(other);
                    if (overlap.Area > minArea * minArea)
                        overlaps.Add((Geometry)overlap);
                }
            }
            return overlaps;
        }
        /// 
        /// 从几何集合中提取有效多边形
        /// 
        private static IEnumerable ExtractValidPolygons(Geometry geom)
        {
            if (geom is Polygon p) return new[] { p };
            if (geom is GeometryCollection coll)
                return coll.Geometries
                    .Where(g => g is Polygon)
                    .Select(g => ValidateGeometry((Geometry)g));
            return Enumerable.Empty();
        }
        #endregion
        #region 验证逻辑
        /// 
        /// 拓扑一致性验证
        /// 
        public static bool ValidateTopology(IEnumerable geometries, double tolerance)
        {
            var index = BuildSTRTree(geometries);
            return geometries.All(g =>
            {
                // 检查自身有效性
                if (!g.IsValid) return false;
                // 检查相邻关系
                return index.Query(g.EnvelopeInternal)
                    .Where(other => g != other)
                    .All(other =>
                        !g.Intersects(other) ||
                        (g.Touches(other) && g.Boundary.Distance(other.Boundary) <= tolerance)
                    );
            });
        }
        #endregion
    }
    /// 
    /// 自定义拓扑异常
    /// 
    public class TopologyException : Exception
    {
        public TopologyException(string message) : base(message) { }
    }
}