using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Vortex.Drawing;
using Vortex.Wrapper.Platform;
using System.Windows.Forms;

namespace Piggy.Vortex
{
    public delegate void onCanvasDraw(PiggyDrawer sender);
    public class PiggyDrawer : IDisposable
    {
        //绘画设备
        private static MultiContextDevice _drawingDevice;
        protected static MultiContextDevice DrawingDevice
        {
            get { return PiggyDrawer._drawingDevice; }
        }
        //目标上下文
        private DrawingContext _targetContext;
        public DrawingContext TargetContext
        {
            get { return _targetContext; }
        }
        //是否多窗体的基础窗体(只允许有一个基础窗体)
        protected bool _baseMultiBase = false;
        //鼠标选择的绘画风格
        protected static LineStyle _mouseStyle;
        //鼠标按下时的坐标(相对于当前绘画的画布)
        protected Point _downPoint = new Point(0, 0);
        //当前绘画画布的起始坐标
        protected Point _canvasPoint = new Point(0, 0);
        //需要绘画的控件
        protected Control _drawControl;
        //需要绘画的控件所在的窗体
        protected Form _controlForm;
        //是否是基础的PiggyDrawer
        protected bool _isBase = false;
        protected static SpriteFont _SongTiFont;
        //背景颜色
        private ColorU _clearColor = ColorU.Black;
        public Color ClearColor
        {
            get { return _clearColor; }
            set { _clearColor = value; DoDraw(); }
        }
        //外部传递进来绘画方法
        private event onCanvasDraw onDraw;

        //Timer
        protected static Timer _frameTimer;
        //缓存起每一个装有MultiContextDevice对象的窗体
        private static IList<PiggyDrawer> drawers = new List<PiggyDrawer>();
        //绘画线条风格
        protected static LineStroke[] _strokes;
        //当前线条风格
        private int _strokeIndex = 0;
        public int StrokeIndex
        {
            get { return _strokeIndex; }
            set { _strokeIndex = value; DoDraw(); }
        }

        public static PiggyDrawer InitToUseD3D(Control sender, Form former)
        {
            return InitToUseD3D(sender, former,null);
        }
        public static PiggyDrawer InitToUseD3D(Control sender, Form former,onCanvasDraw drawEvent)
        {
            PiggyDrawer mDrawer = new PiggyDrawer();
            mDrawer._canvasPoint = WinApi.ClientToScreen(sender.Handle, new Point(0, 0));
            if (drawers.Count == 0)
            {
                _drawingDevice = new MultiContextDevice(sender.Handle);
                if (_mouseStyle == null)
                    _mouseStyle = new LineStyle(1, LineStroke.Dotted);
                if (_SongTiFont == null)
                    _SongTiFont = new SpriteFont("Fonts\\SongTi,18px");
                mDrawer._isBase = true;
                if (_frameTimer == null)
                {
                    _frameTimer = new Timer();
                    _frameTimer.Tick += new EventHandler(frameTimer_Tick);
                }
                if (_strokes==null)
                    _strokes = new LineStroke[] { LineStroke.Solid, LineStroke.Dotted, LineStroke.Dashed, LineStroke.DotDashed, LineStroke.Dual, LineStroke.Smooth,LineStroke.TinyDashed,LineStroke.CombinedDashed };
            }
            mDrawer._targetContext = _drawingDevice.CreateContext(sender.Handle);
            mDrawer._drawControl = sender;
            mDrawer._controlForm = former;
            mDrawer.InitControlEvent();
            drawers.Add(mDrawer);
            if (drawEvent!=null)
                mDrawer.onDraw += drawEvent;
            DrawAll();
            return mDrawer;
        }
        private void InitControlEvent()
        {
            _drawControl.Move += new EventHandler(Control_Move);
            _drawControl.MouseUp+=new MouseEventHandler(drawControl_MouseUp);
            _drawControl.MouseDown+=new MouseEventHandler(drawControl_MouseDown);
            _drawControl.Paint+=new PaintEventHandler(drawControl_Paint);
            _drawControl.Resize+=new EventHandler(drawControl_Resize);
            _controlForm.Move += new EventHandler(Control_Move);
        }
        private void RemoveControlEvent()
        {
            _drawControl.Move -= new EventHandler(Control_Move);
            _drawControl.MouseUp -= new MouseEventHandler(drawControl_MouseUp);
            _drawControl.MouseDown -= new MouseEventHandler(drawControl_MouseDown);
            _drawControl.Paint -= new PaintEventHandler(drawControl_Paint);
            _drawControl.Resize -= new EventHandler(drawControl_Resize);
            _controlForm.Move -= new EventHandler(Control_Move);
            if (onDraw != null)
                onDraw = null;
        }

        public void DoDraw()
        {
            if (_drawingDevice.BeginScene())
            {
                Canvas2D canvas = _targetContext.Canvas;
                //clear target
                canvas.Clear(_clearColor);
                canvas.DrawText(_SongTiFont, new Vector2(5, 15), "你好", ColorU.Black);
                /*
                canvas.DrawText(SpriteFont.Default, new Vector2(5, 15), "formposition=(" + _controlForm.Left + "," + _controlForm.Top + ")", ColorU.Black.MultiplyAlpha(0.25f));
                canvas.DrawText(SpriteFont.Default, new Vector2(5, 25), "Drawposition=(" + _canvasPoint.X + "," + _canvasPoint.Y + ")", ColorU.Black.MultiplyAlpha(0.25f));


                if (_downPoint.X != 0 && _downPoint.Y != 0)
                    canvas.DrawRect(new Rect(_downPoint.X, _downPoint.Y, Cursor.Position.X - _canvasPoint.X, Cursor.Position.Y - _canvasPoint.Y), _mouseStyle, ColorU.Black);
                DoChildDraw(canvas);
                if (onDraw != null)
                    onDraw(this);
                 */
                //end domain (finalizes some device stuff)
                _drawingDevice.EndScene();
                //present backbuffer content 
                _targetContext.Present();
            }
            else
            {
                //try reset drawing device
                _drawingDevice.TryReset();
            }
        }
        //子类必须继承的方法
        public void DoChildDraw(Canvas2D canvas)
        {
        }

        public void Dispose()
        {
            RemoveControlEvent();
            _targetContext.Dispose();
            _controlForm = null;
            _drawControl = null;
            if (_isBase)
            {
                for (int i = 1; i < drawers.Count; i++)
                    _drawingDevice.Dispose();
            }
            drawers.Remove(this);
        }
        private void Control_Move(object sender, EventArgs e)
        {
            _canvasPoint = WinApi.ClientToScreen(_drawControl.Handle, new Point(0, 0));
        }

        private static void DrawAll()
        {
            for (int i = 0; i < drawers.Count; i++)
                (drawers[i] as PiggyDrawer).DoDraw();
        }

        private static void frameTimer_Tick(object sender, EventArgs e)
        {
            DrawAll();
        }
        
        private void drawControl_MouseUp(object sender, MouseEventArgs e)
        {
            _downPoint.X = 0;
            _downPoint.Y = 0;
            _frameTimer.Enabled = false;
            DoDraw();
        }
        private void drawControl_MouseDown(object sender, MouseEventArgs e)
        {
            _downPoint = e.Location;
            _frameTimer.Enabled = true;
        }

        private void drawControl_Paint(object sender, PaintEventArgs e)
        {
            //all we need is present content from back buffer
            _targetContext.Present(); 
        }
        private void drawControl_Resize(object sender, EventArgs e)
        {
            //ask resize device when window size is changed
            _targetContext.Resize();
            //optionally you may call draw content
            DoDraw();
            _canvasPoint = WinApi.ClientToScreen(_drawControl.Handle, new Point(0, 0));
        }
        public LineStyle getCurrentLineStyle(int pBorderWidth)
        {
            return new LineStyle(pBorderWidth, _strokes[_strokeIndex]);
        }
    }
}
