using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.EngineEditor;
using KGIS.Framework.Maps;
using KGIS.Framework.Utils;
using KGIS.Framework.Utils.Helper;
using Kingo.Plugin.EngineEditor.Common;
namespace Kingo.Plugin.EngineEditor.Commands.Tools
{
    /// 
    /// 共边画面
    /// 
    public class ControlsEditingAutoConstrcutPolygonForKDB : BaseToolCmd
    {
        private IMapService _MapService;
        public VerificationOfFeatureNodeDensity density
        {
            get;
            set;
        }
        public override bool Enabled
        {
            get
            {
                if (m_pEditor == null) return false;
                //替换Env
                ESRI.ArcGIS.Carto.ILayer layer = (m_pEditor as EngineEditorClass).TargetLayer;
                if ((m_pEditor as EngineEditorClass).EditState == esriEngineEditState.esriEngineStateEditing && layer != null && (layer as ESRI.ArcGIS.Carto.IFeatureLayer).FeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        public override void OnCreate(object hook)
        {
            base.OnCreate(hook);
        }
        private void ActiveViewEvents_Event_ItemDeleted(object Item)
        {
            if (EditorSettingClass.Instance.IsTraceing)
            {
                this.EndTraceFeedback();
            }
        }
        //激活视图事件_项目已添加
        private void ActiveViewEvents_Event_ItemAdded(object Item)
        {
            if (EditorSettingClass.Instance.IsTraceing)
            {
                this.EndTraceFeedback();
            }
        }
        //注册 活动视图事件_内容更改 事件
        private void ActiveViewEvents_Event_ContentsChanged()
        {
        }
        /// 
        /// 图斑范围更新刷新
        /// 
        /// 
        /// 
        private void M_pAxMapControl_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            try
            {
                if (EditorSettingClass.Instance.IsTraceing && this.m_pTraceFeedback != null)
                {
                    this.FillFeatureCache(this.m_pPointCatched);
                    this.GetBeTracedPolyline();
                    //this.m_pTraceFeedback.SetSplitPolyline(m_pListBeTracePolyline);
                    this.m_pTraceFeedback.ListBeTracePolyline = this.m_pListBeTracePolyline;
                }
            }
            catch (Exception ex)
            {
                LogAPI.Debug("图斑范围更新刷新OnExtentUpdated异常" + ex);
            }
        }
        /// 
        /// 停用
        /// 
        /// 
        public override bool Deactivate()
        {
            base.Deactivate();
            _MapService.getAxMapControl().OnExtentUpdated -= M_pAxMapControl_OnExtentUpdated;
            IActiveViewEvents_Event activeViewEvents_Event = _MapService.getAxMapControl().ActiveView as IActiveViewEvents_Event;
            activeViewEvents_Event.ContentsChanged -= ActiveViewEvents_Event_ContentsChanged;
            activeViewEvents_Event.ItemAdded -= ActiveViewEvents_Event_ItemAdded;
            activeViewEvents_Event.ItemDeleted -= ActiveViewEvents_Event_ItemDeleted;
            this.m_deactivate = true;
            return this.m_deactivate;
        }
        public override void OnClick()
        {
            base.OnClick();
            _MapService = MapsManager.Instance.MapService;
            base.m_pDisplayFeedbackMethod = DisplayFeedbackMethod.Line;
            _MapService.getAxMapControl().OnExtentUpdated += M_pAxMapControl_OnExtentUpdated;
            IActiveViewEvents_Event activeViewEvents_Event = _MapService.getAxMapControl().ActiveView as IActiveViewEvents_Event;
            //注册 活动视图事件_内容更改 事件
            activeViewEvents_Event.ContentsChanged += ActiveViewEvents_Event_ContentsChanged;
            //注册 激活视图事件_项目已添加 事件
            activeViewEvents_Event.ItemAdded += ActiveViewEvents_Event_ItemAdded;
            activeViewEvents_Event.ItemDeleted += ActiveViewEvents_Event_ItemDeleted;
        }
        /// 
        /// 当鼠标按下时
        /// 
        /// 
        /// 
        /// 
        /// 
        public override void OnMouseDown(int Button, int Shift, int X, int Y)
        {
            try
            {
                if (Button == 1)
                {
                    DisplayFeedbackMethod pDisplayFeedbackMethod = this.m_pDisplayFeedbackMethod;
                    if (this.m_pGeometry == null)
                    {
                        switch (pDisplayFeedbackMethod)
                        {
                            case DisplayFeedbackMethod.Line:
                                this.NewPolyline();
                                break;
                            case DisplayFeedbackMethod.Polygon:
                                this.NewPolygon();
                                break;
                            default:
                                break;
                        }
                    }
                    if (pDisplayFeedbackMethod != DisplayFeedbackMethod.Arc)
                    {
                        if (EditorSettingClass.Instance.IsTraceing && (this.m_pDisplayFeedbackMethod == DisplayFeedbackMethod.Polygon || this.m_pDisplayFeedbackMethod == DisplayFeedbackMethod.Line))
                        {
                            IPoint p = this.m_pMapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
                            ISnappingResult snappingResult = null;
                            if (this.m_pSnappingEnv != null && this.m_pSnappingEnv.Enabled)
                            {
                                snappingResult = this.m_pPntSnapper.Snap(p);
                            }
                            if (snappingResult == null && m_pTraceFeedback == null)
                            {
                                m_pTraceFeedback = null;
                                switch (pDisplayFeedbackMethod)
                                {
                                    case DisplayFeedbackMethod.Polygon:
                                        this.AddToFeedback(this.m_pPointCatched);
                                        this.AddPointToPolygon(this.m_pPointCatched);
                                        break;
                                    case DisplayFeedbackMethod.Line:
                                        //this.StartFeedback(this.m_pPointCatched);
                                        this.AddToFeedback(this.m_pPointCatched);
                                        this.AddPointToPolyline(this.m_pPointCatched);
                                        break;
                                }
                            }
                            else if (snappingResult == null && m_pTraceFeedback != null)
                            {
                                IPolyline polyline = this.AddToTraceFeedBack(this.m_pPointCatched);
                                if (polyline != null && !polyline.IsEmpty)
                                {
                                    if (pDisplayFeedbackMethod == DisplayFeedbackMethod.Polygon)
                                    {
                                        this.AddPolylineToPolygon(polyline);
                                        this.AddToFeedback(polyline);
                                    }
                                    else if (pDisplayFeedbackMethod == DisplayFeedbackMethod.Line)
                                    {
                                        this.AddPolylineToPolyline(polyline);
                                        this.AddToFeedback(polyline);
                                        //this.StartFeedback(polyline.ToPoint);
                                    }
                                }
                            }
                            else
                            {
                                try
                                {
                                    base.ListSelectableLayer = MapsManager.Instance.MapService.GetAllVisibleLayerInMap();
                                    //GetAllFeatureLayer();
                                    //if (this.m_pListFeatureCache == null)
                                    //{
                                    try
                                    {
                                        this.FillFeatureCache(this.m_pPointCatched);
                                    }
                                    catch (Exception) { }
                                    this.GetBeTracedPolyline();
                                    //}
                                    IPolyline polyline = this.AddToTraceFeedBack(this.m_pPointCatched);
                                    if (polyline != null && !polyline.IsEmpty)
                                    {
                                        if (pDisplayFeedbackMethod == DisplayFeedbackMethod.Polygon)
                                        {
                                            this.AddPolylineToPolygon(polyline);
                                            this.AddToFeedback(polyline);
                                        }
                                        else if (pDisplayFeedbackMethod == DisplayFeedbackMethod.Line)
                                        {
                                            this.AddPolylineToPolyline(polyline);
                                            this.AddToFeedback(polyline);
                                            //this.StartFeedback(polyline.ToPoint);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                }
                            }
                        }
                        else
                        {
                            m_pTraceFeedback = null;
                            switch (pDisplayFeedbackMethod)
                            {
                                case DisplayFeedbackMethod.Polygon:
                                    this.AddToFeedback(this.m_pPointCatched);
                                    this.AddPointToPolygon(this.m_pPointCatched);
                                    break;
                                case DisplayFeedbackMethod.Line:
                                    //this.StartFeedback(this.m_pPointCatched);
                                    this.AddToFeedback(this.m_pPointCatched);
                                    this.AddPointToPolyline(this.m_pPointCatched);
                                    break;
                            }
                        }
                    }
                    else if (this.m_nArcPointCount == 0)
                    {
                        IPointCollection pointCollection = this.m_pGeometry as IPointCollection;
                        int pointCount = pointCollection.PointCount;
                        if (pointCount >= 1)
                        {
                            IPoint pPoint = pointCollection.get_Point(pointCount - 1);
                            this.AddToArcFeedback(pPoint);
                            this.AddToArcFeedback(this.m_pPointCatched);
                        }
                        else
                        {
                            this.AddToArcFeedback(this.m_pPointCatched);
                        }
                    }
                    else if (this.m_nArcPointCount != 1)
                    {
                        if (this.m_nArcPointCount == 2)
                        {
                            ICircularArc circularArc = this.AddToArcFeedback(this.m_pPointCatched);
                            if (circularArc != null)
                            {
                                this.AddSegmentToPolygon(circularArc as ISegment);
                                this.AddToFeedback((circularArc as ISegment).ToPoint);
                            }
                        }
                    }
                    else
                    {
                        this.AddToArcFeedback(this.m_pPointCatched);
                    }
                    if (this.m_pPointCatched != null)
                    {
                        this.SketchGeometry.Update();
                    }
                    this.RefreshForeground(null);
                }
            }
            catch (Exception ex)
            {
            }
        }
        /// 
        /// 当鼠标移动时
        /// 
        /// 
        /// 
        /// 
        /// 
        public override void OnMouseMove(int Button, int Shift, int X, int Y)
        {
            if (Button == 4)
            {
                return;
            }
            this.m_pPointCatched = this.m_pMapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
            if (this.m_pSnappingEnv != null && this.m_pSnappingEnv.Enabled)
            {
                ISnappingResult snappingResult = this.m_pPntSnapper.Snap(this.m_pPointCatched);
                this.m_pSnappingFeedback.Update(snappingResult, 0);
                if (snappingResult != null)
                {
                    this.m_pPointCatched = snappingResult.Location;
                }
            }
            string strDescription = "";
            IPoint point = null;
            if (this.m_pSnappingEnv != null && this.m_pSnappingEnv.Enabled && SnappingSketchFeedback.Enabled)
            {
                this.RefreshForeground(null);
                point = base.SnappingSketch(this.m_pPointCatched, ref strDescription);
                if (point != null)
                {
                    this.m_pPointCatched = point;
                }
            }
            try
            {
                DisplayFeedbackMethod pDisplayFeedbackMethod = this.m_pDisplayFeedbackMethod;
                if (pDisplayFeedbackMethod == DisplayFeedbackMethod.Arc)
                {
                    if (this.m_pNewArcFeedback == null && this.m_pDisplayFeedback != null)
                    {
                        this.m_pDisplayFeedback.MoveTo(this.m_pPointCatched);
                    }
                    if (this.m_pNewArcFeedback != null)
                    {
                        if (this.m_nArcPointCount == 2)
                        {
                            (this.m_pNewArcFeedback as ESRI.ArcGIS.Display.IDisplayFeedback).MoveTo(this.m_pPointCatched);
                        }
                    }
                }
                else
                {
                    if (EditorSettingClass.Instance.IsTraceing && (this.m_pDisplayFeedbackMethod == DisplayFeedbackMethod.Polygon || this.m_pDisplayFeedbackMethod == DisplayFeedbackMethod.Line))
                    {
                        if (this.m_pTraceFeedback == null && this.m_pDisplayFeedback != null)
                        {
                            this.m_pDisplayFeedback.MoveTo(this.m_pPointCatched);
                        }
                        if (this.m_pTraceFeedback != null)
                        {
                            try
                            {
                                this.m_pTraceFeedback.MoveTo(this.m_pPointCatched);
                            }
                            catch (Exception) { }
                            this.RefreshForeground(null);
                        }
                    }
                    else
                    {
                        switch (pDisplayFeedbackMethod)
                        {
                            case DisplayFeedbackMethod.Polygon:
                                this.m_pDisplayFeedback?.MoveTo(this.m_pPointCatched);
                                break;
                            case DisplayFeedbackMethod.Line:
                                this.m_pDisplayFeedback?.MoveTo(this.m_pPointCatched);
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                PluginServiceInterface.CommonHelper.RecordsErrLog("共边划线OnMouseMove异常", ex);
            }
            if (point != null)
            {
                this.m_pSnappingSketchFeedback.Update(point, strDescription);
            }
        }
        /// 
        /// 刷新
        /// 
        /// 
        public override void Refresh(int hDC)
        {
            this.m_pSnappingFeedback?.Refresh(hDC);
            this.m_pDisplayFeedback?.Refresh(hDC);
            if (EditorSettingClass.Instance.IsTraceing && this.m_pTraceFeedback != null)
            {
                this.m_pTraceFeedback.Refresh(hDC);
            }
        }
        //重新开始反馈
        public override void ReStartFeedback()
        {
            IPointCollection pointCollection = null;
            int num = 0;
            if (this.m_pGeometry != null || !this.m_pGeometry.IsEmpty)
            {
                IGeometryCollection geometryCollection = this.m_pGeometry as IGeometryCollection;
                int geometryCount = geometryCollection.GeometryCount;
                if (geometryCount > 0)
                {
                    this.m_pRing = (geometryCollection.get_Geometry(geometryCollection.GeometryCount - 1) as IRing);
                    pointCollection = (this.m_pRing as IPointCollection);
                    num = pointCollection.PointCount;
                }
                else
                {
                    this.m_pRing = null;
                }
            }
            this.EndFeedback();
            this.EndArcFeedback();
            this.EndTraceFeedback();
            if (pointCollection != null)
            {
                for (int i = 0; i < num; i++)
                {
                    this.AddToFeedback(pointCollection.get_Point(i));
                }
            }
            this.RefreshForeground(null);
        }
        //当鼠标松开时
        public override void OnMouseUp(int Button, int Shift, int X, int Y)
        {
            try
            {
                base.OnMouseUp(Button, Shift, X, Y);
            }
            catch (Exception ex)
            {
                PluginServiceInterface.CommonHelper.RecordsErrLog("共边划线OnMouseUp异常", ex);
            }
        }
        public override void OnKeyDown(int keyCode, int Shift)
        {
            base.OnKeyDown(keyCode, Shift);
        }
        public override void OnKeyUp(int keyCode, int Shift)
        {
            base.OnKeyUp(keyCode, Shift);
        }
        //完成绘制草图(双击事件)
        public override void OnDblClick()
        {
            try
            {
                FinishSketch();
            }
            catch (Exception ex)
            {
                LogAPI.Debug(ex.Message);
                MessageHelper.ShowError(ex.Message);
            }
        }
        public void FinishSketch()
        {
            this.EndFeedback();
            this.EndArcFeedback();
            this.EndTraceFeedback();
            if (m_pGeometry is IPolygon)
            {
                if (!(m_pGeometry as IPolygon).IsClosed)
                {
                    (m_pGeometry as IPolygon).Close();
                }
                (this.m_pGeometry as IPolygon).SimplifyPreserveFromTo();
                if (!this.m_pGeometry.IsEmpty)
                {
                    ConstructionFeature();
                }
            }
            else if (m_pGeometry is IPolyline)
            {
                if (!this.m_pGeometry.IsEmpty)
                {
                    IPolyline polyline = this.m_pGeometry as IPolyline;
                    polyline.SimplifyNetwork();
                    ConstructionFeature();
                }
            }
            if (EditorSettingClass.Instance.OnDrawEnd != null)
            {
                EditorSettingClass.Instance.OnDrawEnd(this, this.m_pGeometry);
            }
            Marshal.ReleaseComObject(this.m_pGeometry);
            if (m_pPath != null)
                Marshal.ReleaseComObject(this.m_pPath);
            if (m_pRing != null)
                Marshal.ReleaseComObject(this.m_pRing);
            this.m_pGeometry = null;
            this.m_pRing = null;
            this.m_pPath = null;
            if (this.SketchGeometry != null)
            {
                this.SketchGeometry.Deactivate();
                this.SketchGeometry = null;
            }
            this.RefreshForeground(null);
        }
        //建设图斑
        public void ConstructionFeature()
        {
            try
            {
                m_pEditor.StartOperation();
                object objMiss = Type.Missing;
                GeometryBagClass enumGeoLines = new GeometryBagClass();
                enumGeoLines.AddGeometry(m_pGeometry, ref objMiss, ref objMiss);
                if (density == null)
                    density = new VerificationOfFeatureNodeDensity(m_pHookHelper);
                if ((m_pEditor as IEngineEditLayers).TargetLayer != null && (m_pEditor as IEngineEditLayers).TargetLayer is IFeatureLayer)
                {
                    IFeatureLayer FeatLayer = (m_pEditor as IEngineEditLayers).TargetLayer as IFeatureLayer;
                    FeatLayer.Selectable = true;
                    IFeatureClass fc = FeatLayer.FeatureClass;
                    IDataset pDataset = fc as IDataset;
                    IWorkspace pWorkspace = m_pEditor.EditWorkspace;
                    IInvalidArea invalidArea = new InvalidAreaClass();
                    //要素构造类
                    IFeatureConstruction pfeatBuild = new FeatureConstructionClass();
                    //开始自动完成构面并保存到fc面图层中
                    IFeatureSelection featsel = FeatLayer as IFeatureSelection;
                    ISelectionSet selSet = featsel.SelectionSet;
                    ESRI.ArcGIS.Display.SimpleFillSymbolClass selectSymboll = new ESRI.ArcGIS.Display.SimpleFillSymbolClass();
                    ESRI.ArcGIS.Display.ISymbol m_LineSymbol = new ESRI.ArcGIS.Display.SimpleLineSymbol() as ESRI.ArcGIS.Display.ISymbol;
                    ((ESRI.ArcGIS.Display.ILineSymbol)m_LineSymbol).Color = GreenColor();
                    selectSymboll.Outline = m_LineSymbol as ESRI.ArcGIS.Display.ILineSymbol;
                    featsel.SelectionSymbol = selectSymboll;
                    string toleranceStr = SysConfigsOprator.GetAppsetingValueByKey("Tolerance");
                    if (!double.TryParse(toleranceStr, out double tolerance))
                    {
                        tolerance = 0.0001;
                    }
                    //从几何图形自动完成-AutoCompleteFromGeometries
                    pfeatBuild.AutoCompleteFromGeometries(FeatLayer.FeatureClass, this.m_pHookHelper.ActiveView.Extent, enumGeoLines, invalidArea, tolerance, pWorkspace, out selSet);
                    IEnumFeature pEnumFeature = MapsManager.Instance.MapService.getAxMapControl().ActiveView.FocusMap.FeatureSelection as IEnumFeature;
                    //pfeatBuild.AutoCompleteFromFeatures(FeatLayer.FeatureClass, this.m_pHookHelper.ActiveView.Extent, pEnumFeature, invalidArea, tolerance, pWorkspace, out selSet);
                    if (selSet != null && selSet.Count > 0)
                    {
                        StringBuilder strb = new StringBuilder();
                        IEnumIDs ids = selSet.IDs;
                        int oid = ids.Next();
                        List featureList = new List();
                        //与之相邻面积最大的多边形
                        //IGeometry geo3 = null;
                        while (oid > 0)
                        {
                            strb.Append(oid + ",");
                            IFeature currFeature = fc.GetFeature(oid);
                            currFeature.Shape.SpatialReference = m_pHookHelper.FocusMap.SpatialReference;
                            #region 注释
                            //if (dataCheckService != null)
                            //{
                            //    dataCheckService.GeometryCheck(currFeature.Shape, FeatLayer);
                            //}
                            //按权属分割、合并图斑
                            //List GeoList = null;
                            //if (selectFeatureLayer != null && KGIS.Framework.Platform.Platform.Instance.SystemType == 1)
                            //{
                            //    GeoList = FeatureAPI.GenerateNewFeature(currFeature.ShapeCopy, selectFeatureLayer.FeatureClass);
                            //}
                            //if (GeoList != null && GeoList.Count > 0)
                            //{
                            //    GeoList[0] = density.Verification(GeoList[0]);
                            //    currFeature.Shape = GeoList[0];
                            //    currFeature.Store();
                            //    featureList.Add(currFeature);
                            //    for (int i = GeoList.Count - 1; i > 0; i--)
                            //    {
                            //        if (GeoList[i].IsEmpty)
                            //            continue;
                            //        IFeature newFeature = fc.CreateFeature();
                            //        newFeature.Shape = GeoList[i];
                            //        newFeature.Store();
                            //        featureList.Add(newFeature);
                            //        strb.Append(newFeature.OID + ",");
                            //    }
                            //} 
                            #endregion
                            IFeatureLayer selectFeatureLayer = FeatLayer;
                            currFeature.Store();
                            featureList.Add(currFeature);
                            oid = ids.Next();
                        }
                        m_pEditor.StopOperation("AUTO");
                        ids.Reset();
                        strb.Remove(strb.Length - 1, 1);
                        _MapService.SelectFeature((FeatLayer.FeatureClass as FeatureClass).BrowseName, strb.ToString(), false);
                    }
                    else
                    {
                        //编辑中止操作
                        m_pEditor.AbortOperation();
                    }
                }
                else
                {
                    MessageHelper.ShowTips("目标图层为空,请开启编辑会话");
                }
                this.m_pHookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewBackground, null, this.m_pHookHelper.ActiveView.Extent);
            }
            catch (Exception ex)
            {
                LogAPI.Debug("画线构面 过程中 双击鼠标 时失败,异常原因: " + ex + " ; ");
                m_pEditor.AbortOperation();
                MessageHelper.ShowError(ex.Message);
            }
        }
        private ESRI.ArcGIS.Display.IColor GreenColor()
        {
            ESRI.ArcGIS.Display.IRgbColor pRGB = new ESRI.ArcGIS.Display.RgbColorClass
            {
                Red = 0,
                Green = 255,
                Blue = 0
            };
            return pRGB;
        }
    }
}