using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Graphics;
using WinFormsGraphicsDevice;
using SysColor = System.Drawing.Color;
using XnaColor = Microsoft.Xna.Framework.Color;
using Rectangle = Microsoft.Xna.Framework.Rectangle;
using System.Text;
using System.Collections.Generic;
using nft.framework.drawing;
using nft.framework;
using Microsoft.Xna.Framework;
using System.Diagnostics;

namespace nft.xna
{

    /// <summary>
    /// このカスタム コントロールは、XNA Framework GraphicsDevice を使用して、
    /// Windows フォームにレンダリングします。
    /// ※サンプルにあったGraphicDeviceContorlを大幅カスタマイズ c477
    /// </summary>
    public class XnaControl : Control
    {
        protected XnaSurface surface = null;
        SurfaceUsage usage;
        #region Initialization

        public XnaControl(SurfaceUsage usage) {
            this.usage = usage;           
        }

        public XnaControl() : this(SurfaceUsage.Normal) {
        }

        public XnaSurface Surface {
            get { return surface; }
        }

        protected override void OnCreateControl()
        {
            if (!DesignMode)
            {
                surface = XnaSurface.CreateForControl(this, usage);
            }
            base.OnCreateControl();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && surface != null)
            {
                surface.Dispose();
                surface = null;
            }
            base.Dispose(disposing);
        }
        #endregion

        #region Paint
        protected override void OnPaint(PaintEventArgs evt)
        {
            if (surface == null) {
                // Assume running in DesignMode.
                PaintErrorMessage(evt.Graphics, Text + "\n\n" + GetType());
            } else {
                try {
                    surface.Draw();
                    Debug.WriteLine(surface.GetDrawStatistics());
                } catch (Exception ex) {
                    string errorMsg = ex.Message;
                    Debug.WriteLine(errorMsg);
                    Debug.WriteLine(ex.StackTrace);
                    if (ex.InnerException != null) {
                        errorMsg = string.Format("[{1}]:{0}", errorMsg,
                            ex.GetType().Name);
                    }
#if DEBUG
                    errorMsg += "\n\n" + ex.StackTrace;
#endif
                    // Show error message with GDI drawings.
                    PaintErrorMessage(evt.Graphics, errorMsg);
                }
            }
        }

        // Called when GraphicsDevice is not available.
        // For example, Device lost or Running in 'DesignMode==true'
        protected virtual void PaintErrorMessage(Graphics graphics, string text)
        {
            graphics.Clear(SysColor.CornflowerBlue);
            using (Brush brush = new SolidBrush(SysColor.Black))
            {
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;
                    graphics.DrawString(text, Font, brush, ClientRectangle, format);
                }
            }
        }

        protected override void OnSizeChanged(EventArgs e) {
            base.OnSizeChanged(e);
            surface.NotifyResize(this);
            Invalidate();
        }

        /*
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
            width = ((width + 1) | 1) - 1;
            height = ((height + 1) | 1) - 1;
            base.SetBoundsCore(x, y, width, height, specified);
        }
        */

        // override to cancel default background fill.
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }
        #endregion

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // XnaControl
            // 
            this.AccessibleRole = System.Windows.Forms.AccessibleRole.None;
            this.ResumeLayout(false);
        }
    }
}
