using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
namespace Kingo.PluginServiceInterface.Helper
{
    /// 
    /// 拓扑帮助类
    /// 
    public class DataCheckTopologyHelper
    {
        /// 
        /// 返回true表示面图层内存在重叠
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static bool CreateTopology(List lstTopologyRule, IWorkspace m_Workspace, List lstFeatureClassTabelName, string objectName = "TDBZSJJ")
        {
            double tolerance = 0.0001;
            IFeatureDataset pFeatDS = null;
            ISchemaLock schemalock = null;
            ITopology topology = null;
            try
            {
                if (m_Workspace == null)
                    throw new Exception("获取默认工作空间为空!");
                pFeatDS = GetFeatureDatasetByName(m_Workspace, objectName);
                if (pFeatDS == null)
                {
                    throw new Exception("当前工程数据中不存在【" + objectName + "】");
                }
                //---------------------------
                //判断当前要素集有没有锁
                schemalock = (ISchemaLock)pFeatDS;
                schemalock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
                //获取拓扑 Topology 是否存在
                CheckTopologyExist(m_Workspace, pFeatDS, "TopologyDataCheck");
                //开始创建拓扑
                topology = CreateTopology(pFeatDS, "TopologyDataCheck", tolerance);
                if (topology == null)
                    throw new Exception("创建拓扑失败");
                //添加要素类到拓扑中
                List lstFeatureClass = new List();
                foreach (string featureClassName in lstFeatureClassTabelName)
                {
                    IFeatureClass pFatureClass = (m_Workspace as IFeatureWorkspace).OpenFeatureClass(featureClassName);
                    string inFeatureClassPath = System.IO.Path.Combine((pFatureClass as IDataset).Workspace.PathName, pFatureClass.FeatureDataset.Name, featureClassName);
                    topology.AddClass(pFatureClass, 1, 1, 1, false);
                    lstFeatureClass.Add(pFatureClass);
                }
                foreach (ITopologyRule topologyRule in lstTopologyRule)
                {
                    //把topology对象强制转换到ITopologyRuleContainer对象,然后添加拓扑规则
                    ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology;
                    if (topologyRuleContainer.get_CanAddRule(topologyRule))
                    {
                        topologyRuleContainer.AddRule(topologyRule);
                    }
                    else
                    {
                        throw new ArgumentException("无法将指定的规则添加到拓扑中");
                    }
                }
                // 获取验证拓扑的范围并且验证拓扑
                IGeoDataset geoDataset = (IGeoDataset)topology;
                IEnvelope envelope = geoDataset.Extent;
                ValidateTopology(topology, envelope);
                bool b = FindAllErrorFeatures(topology, envelope, lstFeatureClass);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(geoDataset);
                foreach (IFeatureClass item in lstFeatureClass)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(item);
                }
                foreach (ITopologyRule rule in lstTopologyRule)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(rule);
                }
                return b;
            }
            catch (Exception ex)
            {
                throw new Exception("拓扑检查发生异常:" + ex.Message.ToString());
            }
            finally
            {
                if (topology != null)
                {
                    Marshal.ReleaseComObject(topology);
                }
                if (m_Workspace != null && pFeatDS != null)
                {
                    //获取拓扑 Topology 是否存在,存在则删除
                    CheckTopologyExist(m_Workspace, pFeatDS, "TopologyDataCheck");
                }
                if (schemalock != null)
                {
                    schemalock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
                    Marshal.ReleaseComObject(schemalock);
                }
                if (pFeatDS != null)
                {
                    Marshal.ReleaseComObject(pFeatDS);
                }
                if (m_Workspace != null)
                {
                    Marshal.ReleaseComObject(m_Workspace);
                }
            }
        }
        /// 
        /// 判断拓扑是否存在,存在则删除
        /// 
        /// 工作空间
        /// 要素集
        /// 拓扑名称
        private static void CheckTopologyExist(IWorkspace m_Workspace, IFeatureDataset pFeatDS, string topologyName)
        {
            try
            {
                if (m_Workspace == null || pFeatDS == null)
                {
                    return;
                }
                bool bTopExists = (m_Workspace as IWorkspace2).get_NameExists(esriDatasetType.esriDTTopology, topologyName);
                if (bTopExists)
                {
                    //删除已存在拓扑
                    ITopologyContainer topologyContainer = (ITopologyContainer)pFeatDS;
                    if (topologyContainer != null)
                    {
                        ITopology topologyTemp = topologyContainer.get_TopologyByName(topologyName);
                        if (topologyTemp != null)
                        {
                            //删除拓扑
                            IDataset pDatasetTemp = (IDataset)topologyTemp;
                            pDatasetTemp.Delete();
                            Marshal.ReleaseComObject(pDatasetTemp);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("删除拓扑失败:" + ex.Message.ToString());
            }
        }
        /// 
        /// 创建拓扑
        /// 
        /// 
        /// 
        /// 
        /// 
        private static ITopology CreateTopology(IFeatureDataset pFtDs, string pTopologyName, double clusterTolerance = 0)
        {
            if (pFtDs == null)
                return null;
            ISchemaLock schemaLock = (ISchemaLock)pFtDs;
            try
            {
                schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
                // 创建拓扑
                ITopologyContainer2 topologyContainer = (ITopologyContainer2)pFtDs;
                ITopology topology = topologyContainer.CreateTopology(pTopologyName, clusterTolerance == 0 ? topologyContainer.DefaultClusterTolerance : clusterTolerance, -1, "");
                return topology;
            }
            catch (Exception ex)
            {
                throw new Exception("创建拓扑异常:" + ex.Message.ToString());
            }
            finally
            {
                schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
            }
        }
        /// 
        /// 通过名称获取要素集
        /// 
        /// 
        /// 
        /// 
        public static IFeatureDataset GetFeatureDatasetByName(IWorkspace workspace, string dsName)
        {
            string strFeatureDSName = "";
            IFeatureDataset pResultFDS = null;
            IEnumDataset pEnumDS = workspace.get_Datasets(esriDatasetType.esriDTFeatureDataset);
            pEnumDS.Reset();
            IDataset pDS = pEnumDS.Next();
            while (!(pDS == null))
            {
                strFeatureDSName = GetFeatureObjectName(pDS.Name);
                if (strFeatureDSName.Equals(dsName))
                {
                    pResultFDS = (IFeatureDataset)pDS;
                    break;
                }
                pDS = pEnumDS.Next();
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumDS);
            return pResultFDS;
        }
        /// 
        /// 去掉".",得到名称缩写
        /// 
        /// 
        /// 
        private static string GetFeatureObjectName(string objectName)
        {
            int index = objectName.LastIndexOf(".");
            if (index >= 0)
            {
                return objectName.Substring(index + 1);
            }
            else
            {
                return objectName;
            }
        }
        /// 
        /// 检查建立的拓扑
        /// 
        /// 
        /// 
        private static void ValidateTopology(ITopology topology, IEnvelope envelope)
        {
            // Get the dirty area within the provided envelope.
            IPolygon locationPolygon = new Polygon() as IPolygon;
            ISegmentCollection segmentCollection = (ISegmentCollection)locationPolygon;
            segmentCollection.SetRectangle(envelope);
            IPolygon polygon = topology.get_DirtyArea(locationPolygon);
            // If a dirty area exists, validate the topology.
            if (!polygon.IsEmpty)
            {
                // Define the area to validate and validate the topology.
                IEnvelope areaToValidate = polygon.Envelope;
                IEnvelope areaValidated = topology.ValidateTopology(areaToValidate);
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(locationPolygon);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(polygon);
        }
        /// 
        /// 给定拓扑和查找的范围,返回所有的拓扑错误要素
        /// 
        /// 
        /// 
        public static bool FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent, List lstFeatureClass)
        {
            try
            {
                //获取坐标系
                IErrorFeatureContainer errorFeatureContainer = (IErrorFeatureContainer)topology;
                IGeoDataset geoDataset = (IGeoDataset)topology;
                ISpatialReference spatialReference = geoDataset.SpatialReference;
                ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology;
                //遍历拓扑规则
                IEnumRule enumRule = topologyRuleContainer.Rules;
                enumRule.Reset();
                IRule rule = null;
                while ((rule = enumRule.Next()) != null)
                {
                    //获取当前拓扑规则的拓扑错误并遍历
                    ITopologyRule topologyRule = (ITopologyRule)rule;
                    IEnumTopologyErrorFeature enumTopologyErrorFeature = errorFeatureContainer.get_ErrorFeatures(spatialReference, topologyRule, searchExtent, true, true);
                    ITopologyErrorFeature topologyErrorFeature = null;
                    while ((topologyErrorFeature = enumTopologyErrorFeature.Next()) != null)
                    {
                        if (topologyErrorFeature.OriginOID <= 0)
                        {
                            if (topologyErrorFeature == null || (topologyErrorFeature as IFeature).ShapeCopy.IsEmpty)
                            {
                                continue;
                            }
                            IGeometryCollection geometryCollection = (topologyErrorFeature as IFeature).ShapeCopy as IGeometryCollection;
                            if (geometryCollection == null)
                            {
                                continue;
                            }
                        }
                        GC.Collect();
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(topologyErrorFeature);
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //强制回收
                GC.Collect();
                GC.WaitForFullGCComplete();
            }
        }
    }
}