using System;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using KGIS.Framework.EngineEditor;
using KGIS.Framework.Maps;
using KGIS.Framework.Platform;
using KGIS.Framework.Utils;
using KGIS.Framework.Utils.Helper;
using Kingo.Plugin.EngineEditor.Common;
using Kingo.PluginServiceInterface;
using UIShell.OSGi;
namespace Kingo.Plugin.EngineEditor.Commands.Tools
{
    /// 
    /// 整形要素工具
    /// 
    public class ControlsEditingReshapeTool : BaseToolCmd
    {
        public VerificationOfFeatureNodeDensity density
        {
            get;
            set;
        }
        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, ESRI.ArcGIS.Controls.IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            if (EditorSettingClass.Instance.IsTraceing && this.m_pTraceFeedback != null)
            {
                try
                {
                    this.FillFeatureCache(this.m_pPointCatched);
                }
                catch { }
                this.GetBeTracedPolyline();
                //this.m_pTraceFeedback.SetSplitPolyline(m_pListBeTracePolyline);
                this.m_pTraceFeedback.ListBeTracePolyline = this.m_pListBeTracePolyline;
            }
        }
        public override bool Deactivate()
        {
            base.Deactivate();
            MapsManager.Instance.MapService.getAxMapControl().OnExtentUpdated -= M_pAxMapControl_OnExtentUpdated;
            IActiveViewEvents_Event activeViewEvents_Event = base.m_pMapControl.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();
            base.m_pDisplayFeedbackMethod = DisplayFeedbackMethod.Line;
            MapsManager.Instance.MapService.getAxMapControl().OnExtentUpdated += M_pAxMapControl_OnExtentUpdated;
            IActiveViewEvents_Event activeViewEvents_Event = base.m_pMapControl.ActiveView as IActiveViewEvents_Event;
            activeViewEvents_Event.ContentsChanged += ActiveViewEvents_Event_ContentsChanged;
            activeViewEvents_Event.ItemAdded += ActiveViewEvents_Event_ItemAdded;
            activeViewEvents_Event.ItemDeleted += ActiveViewEvents_Event_ItemDeleted;
        }
        public override bool Enabled
        {
            get
            {
                try
                {
                    if (m_pEditor.EditState != esriEngineEditState.esriEngineStateEditing)
                    {
                        return false;
                    }
                    IFeatureLayer featureLayer = (m_pEditor as IEngineEditLayers).TargetLayer;
                    if (featureLayer == null || featureLayer.FeatureClass == null)
                    {
                        return false;
                    }
                    if ((featureLayer as IFeatureSelection).SelectionSet.Count <= 0)
                    {
                        return false;
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    LogAPI.Debug("整形要素Enabled异常:" + ex.Message);
                    return false;
                }
            }
        }
        public override void OnMouseDown(int Button, int Shift, int X, int Y)
        {
            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
                        {
                            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);
                                }
                            }
                        }
                    }
                    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);
            }
        }
        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 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)
                        {
                            this.m_pTraceFeedback.MoveTo(this.m_pPointCatched);
                            this.RefreshForeground(null);
                        }
                    }
                    else
                    {
                        switch (pDisplayFeedbackMethod)
                        {
                            case DisplayFeedbackMethod.Polygon:
                                if (this.m_pDisplayFeedback != null)
                                {
                                    this.m_pDisplayFeedback.MoveTo(this.m_pPointCatched);
                                }
                                break;
                            case DisplayFeedbackMethod.Line:
                                if (this.m_pDisplayFeedback != null)
                                {
                                    this.m_pDisplayFeedback.MoveTo(this.m_pPointCatched);
                                }
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //FormReportException.Report(ex);
            }
            if (point != null)
            {
                this.m_pSnappingSketchFeedback.Update(point, strDescription);
            }
        }
        public override void Refresh(int hDC)
        {
            if (this.m_pSnappingFeedback != null)
            {
                this.m_pSnappingFeedback.Refresh(hDC);
            }
            if (this.m_pDisplayFeedback != null)
            {
                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)
        {
            base.OnMouseUp(Button, Shift, X, Y);
        }
        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
            {
                int selectIdZYQ = 1;
                IUcZYQMagrHelper ucZYQMagrHelper = null;
                ProjectInfo ProInfo = MapsManager.Instance.MapService.GetProjectInfo() as ProjectInfo;
                if (ProInfo != null && ProInfo.ProjType == EnumProjType.BHTBTQ && Platform.Instance.SystemType == SystemTypeEnum.BGFWCG)
                {
                    ucZYQMagrHelper = BundleRuntime.Instance.GetFirstOrDefaultService();
                    if (ucZYQMagrHelper != null)
                    {
                        selectIdZYQ = ucZYQMagrHelper.GetCheckedID();
                    }
                }
                FinishSketch();
                if (ucZYQMagrHelper != null)
                {
                    ucZYQMagrHelper.AddMask(selectIdZYQ);
                }
            }
            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)
                {
                    DrawAndReshape();
                }
            }
            else if (m_pGeometry is IPolyline)
            {
                IPolyline polyline = this.m_pGeometry as IPolyline;
                polyline.SimplifyNetwork();
                if (!this.m_pGeometry.IsEmpty)
                {
                    DrawAndReshape();
                }
            }
            if (EditorSettingClass.Instance.OnDrawEnd != null)
            {
                EditorSettingClass.Instance.OnDrawEnd(this, this.m_pGeometry);
            }
            ComReleaser.ReleaseCOMObject(this.m_pGeometry);
            if (m_pPath != null)
                ComReleaser.ReleaseCOMObject(this.m_pPath);
            if (m_pRing != null)
                ComReleaser.ReleaseCOMObject(this.m_pRing);
            this.m_pGeometry = null;
            ComReleaser.ReleaseCOMObject(this.m_pRing);
            this.m_pRing = null;
            ComReleaser.ReleaseCOMObject(this.m_pPath);
            this.m_pPath = null;
            if (this.SketchGeometry != null)
            {
                this.SketchGeometry.Deactivate();
                this.SketchGeometry = null;
            }
            this.RefreshForeground(null);
        }
        private void DrawAndReshape()
        {
            try
            {
                if (density == null)
                {
                    density = new VerificationOfFeatureNodeDensity(this.m_pHookHelper);
                }
                IPointCollection reshapePath = new PathClass();
                reshapePath.AddPointCollection(m_pGeometry as IPointCollection);
                //reshape the selected feature
                m_pEditor.StartOperation();
                IFeatureLayer featureLayer = (m_pEditor as IEngineEditLayers).TargetLayer as IFeatureLayer;
                IEnumIDs enumIDs = (featureLayer as IFeatureSelection).SelectionSet.IDs;
                enumIDs.Reset();
                int oid = -1;
                while ((oid = enumIDs.Next()) > -1)
                {
                    IFeature item = featureLayer.FeatureClass.GetFeature(oid);
                    if (item.ShapeCopy is IPolyline)
                    {
                        IPolyline polyline = item.ShapeCopy as IPolyline;
                        polyline.Reshape(reshapePath as IPath);
                        //修改人:李忠盼 修改时间:20181102 图形为空不赋值
                        if (polyline == null || polyline.IsEmpty)
                        {
                            return;
                        }
                        item.Shape = polyline;
                        item.Store();
                    }
                    else if (item.ShapeCopy is IPolygon)
                    {
                        IGeometryCollection geometryCollection = item.ShapeCopy as IGeometryCollection;
                        IRing ring = null;
                        for (int i = 0; i < geometryCollection.GeometryCount; i++)
                        {
                            ring = geometryCollection.get_Geometry(i) as IRing;
                            try
                            {
                                ring.Reshape(reshapePath as IPath);
                            }
                            catch (Exception exce)
                            {
                                LogAPI.Debug("ring.Reshape(reshapePath as IPath) :" + exce.Message);
                                LogAPI.Debug("ring.Reshape(reshapePath as IPath) :" + exce.StackTrace);
                            }
                        }
                        IGeometry pGeometry = geometryCollection as IGeometry;
                        //修改人:李忠盼 修改时间:20181102 图形为空不赋值
                        if (pGeometry == null || pGeometry.IsEmpty)
                        {
                            return;
                        }
                        pGeometry = density.Verification(pGeometry);
                        item.Shape = pGeometry;
                        item.Store();
                    }
                }
                m_pEditor.StopOperation("修整要素");
            }
            catch (Exception ex)
            {
                m_pEditor.AbortOperation();
                LogAPI.Debug("修整要素失败:" + ex.Message);
                MessageHelper.ShowError("修整要素失败:" + ex.Message);
            }
            RefreshForeground();
            m_pHookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewBackground | esriViewDrawPhase.esriViewGeoSelection, null, m_pHookHelper.ActiveView.Extent);
        }
    }
}