using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;

namespace Common.system
{
    internal enum ZPenType : byte
    {
        Pen = 1,
        Erase = 2
    };

    /// <summary>
    /// 画板线模型
    /// </summary>
    internal class ZbbPage
    {
        /// <summary>
        /// 线
        /// </summary>
        public List<ZbbPageStep> lines { get; set; }

        /// <summary>
        /// 历史记录
        /// </summary>
        public List<ZbbPageStep> lines_histoty { get; set; }

        /// <summary>
        /// 画板模型
        /// </summary>
        public ZbbPage()
        {
            lines = new List<ZbbPageStep>();
            lines_histoty = new List<ZbbPageStep>();
        }
    }

    internal class ZbbPageStep
    {
        public StrokeCollection lines_curr { get; set; }
        public StrokeCollection lines_add { get; set; }
        public StrokeCollection lines_remove { get; set; }

        public ZbbPageStep()
        {
            lines_curr = new StrokeCollection();
            lines_add = new StrokeCollection();
            lines_remove = new StrokeCollection();
        }
    }

    public class BlackboardNew
    {
        private InkCanvas _mCanvas;

        //private ZPenType type = ZPenType.Pen;
        /// <summary>
        /// 当前页索引
        /// </summary>
        private int _pagenum;

        /// <summary>
        /// 橡皮大小
        /// </summary>
        private readonly int _erasesize = 64;

        /// <summary>
        /// 笔粗细
        /// </summary>
        private readonly int _pensize = 3;

        /// <summary>
        /// 是否在进行撤销恢复操作
        /// </summary>
        private int _undoOrRedo;

        /// <summary>
        /// 笔颜色
        /// </summary>
        private Color _pencolor;

        /// <summary>
        /// 所有画板线
        /// </summary>
        private readonly List<ZbbPage> _strokesPageAll = new List<ZbbPage>();

        // 添加这个变量是因为在用橡皮擦时 一次操作会触发多次StrokesChanged回掉 这里是把多次回掉合并在一起
        private ZbbPageStep _step;

        public BlackboardNew(InkCanvas canvas)
        {
            Init(canvas, Colors.White);
        }

        public BlackboardNew(InkCanvas canvas, Color pencolor)
        {
            Init(canvas, pencolor);
        }

        private DrawingAttributes _drawingAttributes;

        private void Init(InkCanvas canvas, Color mpencolor)
        {
            _mCanvas = canvas;
            this._pencolor = mpencolor;
            ZbbPage page = new ZbbPage();
            page.lines.Add(new ZbbPageStep());
            _strokesPageAll.Add(page);
            if (canvas != null)
            {
                canvas.EditingMode = InkCanvasEditingMode.Ink;
                _drawingAttributes = new DrawingAttributes();
                canvas.DefaultDrawingAttributes = _drawingAttributes;
                _drawingAttributes.Width = _pensize;
                _drawingAttributes.Height = _pensize;
                _drawingAttributes.Color = this._pencolor;
                _drawingAttributes.FitToCurve = true;
                _drawingAttributes.IgnorePressure = false;
                canvas.Strokes.StrokesChanged += Strokes_StrokesChanged;
                canvas.StrokeCollected += Canvas_StrokeCollected;
                canvas.StrokeErasing += Canvas_StrokeErasing;
                canvas.StrokeErased += Canvas_StrokeErased;
                canvas.MouseUp += Canvas_MouseUp;
            }
        }

        private void Canvas_StrokeErasing(object sender, InkCanvasStrokeErasingEventArgs e)
        {
            _undoOrRedo = 0;
        }

        private void Canvas_StrokeErased(object sender, RoutedEventArgs e) { }

        private void Canvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) { }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_step != null)
            {
                if (_pagenum + 1 > _strokesPageAll.Count)
                {
                    ZbbPage pagetemp = new ZbbPage();
                    pagetemp.lines.Add(new ZbbPageStep());
                    _strokesPageAll.Add(pagetemp);
                }
                try
                {
                    ZbbPage page = _strokesPageAll[_pagenum];
                    if (page != null)
                    {
                        _step.lines_curr.Add(_mCanvas.Strokes);
                        page.lines.Add(_step);
                        _step = null;
                    }
                }
                catch (Exception ex)
                {
                    if (_strokesPageAll != null)
                    {
                        if (_strokesPageAll.Count == 0)
                        {
                            ZbbPage pagetemp = new ZbbPage();
                            pagetemp.lines.Add(new ZbbPageStep());
                            _strokesPageAll.Add(pagetemp);
                        }
                    }
                    LogHelper.Logerror.Error("【画板】（Canvas_MouseUp）添加失败，strokes_page_all为0，" + ex.Message, ex);
                }
            }
        }

        private void Strokes_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
        {
            if (_undoOrRedo > 0)
            {
                _undoOrRedo -= 1;
                return;
            }
            if (_step == null)
            {
                _step = new ZbbPageStep();
            }

            // 笔模式
            if (e.Added.Count > 0 && e.Removed.Count == 0)
            {
                _step.lines_add.Add(e.Added);
            }
            // 橡皮模式 会多次进入回掉
            else if (e.Removed.Count > 0)
            {
                _step.lines_add.Add(e.Added);
                for (int i = 0; i < e.Removed.Count; i++)
                {
                    Stroke removeItem = e.Removed[i];
                    if (_step.lines_add.Contains(removeItem))
                    {
                        _step.lines_add.Remove(removeItem);
                    }
                    else
                    {
                        _step.lines_remove.Add(removeItem);
                    }
                }
            }
        }

        // public方法 笔
        public void change_pen(Color color)
        {
            //this.type = ZPenType.Pen;
            DrawingAttributes drawingAttributes = new DrawingAttributes();
            _mCanvas.DefaultDrawingAttributes = drawingAttributes;
            drawingAttributes.Color = color;
            drawingAttributes.Width = _pensize;
            drawingAttributes.Height = _pensize;
            drawingAttributes.FitToCurve = true;
            drawingAttributes.IgnorePressure = false;
            _mCanvas.EditingMode = InkCanvasEditingMode.Ink;
        }

        // 橡皮
        public void change_erase()
        {
            //this.type = ZPenType.Erase;
            _mCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
            _mCanvas.EraserShape = new EllipseStylusShape(_erasesize, _erasesize, 0);
        }

        // 撤销
        public void Undo()
        {
            ZbbPage page = _strokesPageAll[_pagenum];
            if (page != null && _mCanvas.Strokes.Count > 0 && page.lines.Count > 1)
            {
                ZbbPageStep last = page.lines.Last();
                page.lines.Remove(last);
                page.lines_histoty.Add(last);
                if (page.lines.Last().lines_curr.Count > 0)
                {
                    _undoOrRedo = 2;
                }
                else
                {
                    _undoOrRedo = 1;
                }
                _mCanvas.Strokes.Clear();
                _mCanvas.Strokes.Add(page.lines.Last().lines_curr);
            }
        }

        // 恢复
        public void Redo()
        {
            ZbbPage page = _strokesPageAll[_pagenum];
            if (page != null && page.lines_histoty.Count > 0)
            {
                ZbbPageStep line = page.lines_histoty[page.lines_histoty.Count - 1];
                page.lines.Add(line);
                page.lines_histoty.Remove(line);
                if (page.lines.Last().lines_curr.Count > 0)
                {
                    _undoOrRedo = 2;
                }
                else
                {
                    _undoOrRedo = 1;
                }
                _mCanvas.Strokes.Clear();
                _mCanvas.Strokes.Add(page.lines.Last().lines_curr);
            }
        }

        // 清空
        public void Clear()
        {
            //ZBBPage page = new ZBBPage();
            //page.lines.Add(new ZBBPageStep());
            //page.lines = new List<ZBBPageStep>();
            //page.lines_histoty = new List<ZBBPageStep>();
            //strokes_page_all.Add(page);
            _strokesPageAll.Clear();
            _mCanvas.Strokes.Clear();
            //for (int i=0;i< strokes_page_all.Count;i++)
            //{
            //    ZBBPage page = strokes_page_all[pagenum];
            //    if (page != null)
            //    {
            //        m_canvas.Strokes.Clear();
            //        page.lines_histoty.Clear();
            //        page.lines.Clear();
            //        page.lines.Add(new ZBBPageStep());
            //    }
            //}
        }

        /// <summary>
        /// 翻页
        /// </summary>
        /// <param name="mpagenum"></param>
        public void Changepage(int mpagenum)
        {
            if (_pagenum != mpagenum)
            {
                _pagenum = mpagenum;
                //新增页
                if (_pagenum >= _strokesPageAll.Count)
                {
                    int numadd = _pagenum - _strokesPageAll.Count + 1;
                    for (int i = 0; i < numadd; i++)
                    {
                        ZbbPage pagetemp = new ZbbPage();
                        pagetemp.lines.Add(new ZbbPageStep());
                        _strokesPageAll.Add(pagetemp);
                    }
                }
                ZbbPage page = _strokesPageAll[_pagenum];
                if (page != null && page.lines.Count > 0)
                {
                    if (page.lines.Last().lines_curr.Count > 0)
                    {
                        _undoOrRedo += 1;
                    }
                    if (_mCanvas.Strokes.Count > 0)
                    {
                        _undoOrRedo += 1;
                        _mCanvas.Strokes.Clear();
                    }
                    //StrokeCollection strokes = new StrokeCollection();
                    StylusPointCollection mstylusPoints = new StylusPointCollection();
                    //System.Windows.Input.StylusPointDescription stylusPointDescription = new StylusPointDescription();
                    StylusPoint mstylusPoint = new StylusPoint { X = 580, Y = 212 };
                    mstylusPoints.Add(mstylusPoint);
                    Stroke stroke;
                    mstylusPoint.X = 581;
                    mstylusPoint.Y = 213;
                    mstylusPoints.Add(mstylusPoint);
                    stroke = new Stroke(mstylusPoints);
                    page.lines.Last().lines_curr.Add(stroke);
                    _mCanvas.Strokes.Add(page.lines.Last().lines_curr);
                }
            }
        }

        private StylusPointCollection _stylusPoints = new StylusPointCollection();
        private StylusPoint _stylusPoint;
        private Stroke _stroke;
        private bool _isFirst = true;

        public void Changepages
        (
            double x,
            double y,
            bool mnew,
            Color color,
            int size,
            int i,
            float pressure
        )
        {
            if (mnew)
            {
                if (_stroke != null && _stroke.StylusPoints.Count > 1)
                {
                    _isFirst = true;
                    try
                    {
                        if (_strokesPageAll.Count <= i)
                        {
                            ZbbPage pagetemp = new ZbbPage();
                            pagetemp.lines.Add(new ZbbPageStep());
                            _strokesPageAll.Add(pagetemp);
                        }
                        _strokesPageAll[i].lines.Last().lines_curr.Add(_stroke);
                    }
                    catch (Exception ex)
                    {
                        if (_strokesPageAll != null)
                        {
                            if (_strokesPageAll.Count == 0)
                            {
                                ZbbPage pagetemp = new ZbbPage();
                                pagetemp.lines.Add(new ZbbPageStep());
                                _strokesPageAll.Add(pagetemp);
                            }
                        }
                        LogHelper.Logerror.Error("【画板】（changepages）添加失败，strokes_page_all为0，" + ex.Message, ex);
                    }
                }
                _stylusPoints = new StylusPointCollection();
                _stylusPoint = new StylusPoint();
                _stroke = null;
            }
            else
            {
                if (_isFirst)
                {
                    _stylusPoint.X = x;
                    _stylusPoint.Y = y;
                    //_color.A = (byte)(Pressure * 255f);
                    //stylusPoint.PressureFactor = Pressure;
                    _stylusPoints.Add(_stylusPoint);
                    if (_stylusPoints.Count > 1)
                    {
                        _stroke = new Stroke(_stylusPoints);
                        _drawingAttributes = new DrawingAttributes
                        {
                            Color = color,
                            Width = size * 4.5,
                            Height = size * 4.5,
                            FitToCurve = true,
                            //IsHighlighter =true,
                            IgnorePressure = true
                        };
                        _stroke.DrawingAttributes = _drawingAttributes;
                        _mCanvas.Strokes.Add(_stroke);
                        _isFirst = false;
                    }
                }
                else
                {
                    if (_mCanvas.Strokes.Count > 0)
                    {
                        _stylusPoint.X = x;
                        _stylusPoint.Y = y;
                        _stylusPoints.Add(_stylusPoint);
                        _stroke = new Stroke(_stylusPoints);
                        _drawingAttributes = new DrawingAttributes
                        {
                            Color = color,
                            Width = size * 4.5,
                            Height = size * 4.5,
                            FitToCurve = true,
                            IgnorePressure = false
                        };
                        _stroke.DrawingAttributes = _drawingAttributes;
                        _mCanvas.Strokes[_mCanvas.Strokes.Count - 1] = _stroke;
                    }
                }
            }
        }

        //public void changepages(double _x, double _y, bool mnew, Color _color, int _size, int i)
        //{
        //    try
        //    {
        //        if (mnew)
        //        {
        //            if (stroke != null && stroke.StylusPoints.Count > 1)
        //            {
        //                drawingAttributes = new DrawingAttributes();
        //                //m_canvas.DefaultDrawingAttributes = drawingAttributes;
        //                drawingAttributes.Color = _color;
        //                drawingAttributes.Width = _size * 5;
        //                drawingAttributes.Height = _size * 5;
        //                drawingAttributes.FitToCurve = true;
        //                drawingAttributes.IgnorePressure = false;

        //                stroke.DrawingAttributes = drawingAttributes;
        //                //m_canvas.DefaultDrawingAttributes= drawingAttributes;

        //                m_canvas.Strokes.Add(stroke);
        //                strokes_page_all[i].lines.Last().lines_curr.Add(stroke);

        //                //int currCount= strokes_page_all[i].lines.Last().lines_curr.Count;
        //                //if (currCount > 0)
        //                //{
        //                //    strokes_page_all[i].lines.Last().lines_curr[currCount - 1] = stroke;
        //                //}
        //                stroke = null;
        //            }
        //            stylusPoints = new StylusPointCollection();
        //            stylusPoint = new StylusPoint();
        //            //stroke = new Stroke(stylusPoints);
        //            //stroke = null;
        //        }
        //        else
        //        {
        //            //stylusPoints = new StylusPointCollection();
        //            //stylusPoint = new StylusPoint();
        //            stylusPoint.X = _x;
        //            stylusPoint.Y = _y;
        //            stylusPoints.Add(stylusPoint);
        //            stroke = new Stroke(stylusPoints);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.Logerror.Error("【XHMicroLessonSystemWindow】（changepages）点阵比书写报错：" + ex.Message, ex);
        //    }
        //}
    }
}