using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MikuMikuDance.XNA;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace MMDXWinFormsExpantion
{
    /// <summary>
    /// MMDXFormExpantionの標準コントロール
    /// </summary>
    public partial class MMDXExControl : UserControl
    {
        /// <summary>
        /// MikuMikuDance for XNAオブジェクト
        /// </summary>
        [Browsable(false)]
        public MikuMikuDanceXNA MMDX { get { return MMDXEx.MMDX; } }
        /// <summary>
        /// コンテントマネージャ
        /// </summary>
        [Browsable(false)]
        public ContentManager Content { get { return MMDXEx.Content; } }
        /// <summary>
        /// グラフィックスデバイス
        /// </summary>
        [Browsable(false)]
        public GraphicsDevice GraphicsDevice { get { return MMDXEx.GraphicsDevice; } }
        /// <summary>
        /// MMDXExpantion
        /// </summary>
        [Browsable(false)]
        public MMDXExpantion MMDXEx { get; private set; }
        /// <summary>
        /// 初期化イベント
        /// </summary>
        public event EventHandler Initialize;
        /// <summary>
        /// Updateイベント。XNAのUpdate処理はこの時に行う
        /// </summary>
        public event EventHandler UpdateEvent;
        /// <summary>
        /// 描画イベント。XNAの描画はこの時に行う
        /// </summary>
        public event EventHandler DrawEvent;
        /// <summary>
        /// 既定のコンストラクタ
        /// </summary>
        public MMDXExControl()
        {
            InitializeComponent();
        }
        /// <summary>
        /// コントロールが作成された時の処理
        /// </summary>
        protected override void OnCreateControl()
        {
            if (!DesignMode)
            {//実行時は
                //MMDXExpantionクラスを作成
                MMDXEx = new MMDXExpantion(this);
                //初期化イベントをコール
                if (Initialize != null)
                    Initialize(this, EventArgs.Empty);
                //定期的にUpdateやdrawがコールされるようにフック
                //Lambda式で書いてみた。
                Application.Idle += (object sender, EventArgs e) => Invalidate();
            }
            base.OnCreateControl();
        }
        /// <summary> 
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            if (MMDXEx != null)
                MMDXEx.Dispose(disposing);
            base.Dispose(disposing); 
        }
        //描画処理
        /// <summary>
        /// ペイントメッセージが飛んできた時の処理
        /// </summary>
        /// <param name="e">ペイントメッセージ引数</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (UpdateEvent != null)
                UpdateEvent(this, EventArgs.Empty);
            if (MMDXEx != null)
            {
                string beginError = MMDXEx.BeginDraw();
                if (string.IsNullOrEmpty(beginError))
                {
                    if (DrawEvent != null)
                        DrawEvent(this, EventArgs.Empty);
                    MMDXEx.EndDraw();
                }
                else
                {
                    DrawErrorMsg(e.Graphics, beginError);
                }
            }
            else
            {
                DrawErrorMsg(e.Graphics, Text + "\n\n" + GetType());
            }
            base.OnPaint(e);
        }
        //エラー文字列の描画
        private void DrawErrorMsg(System.Drawing.Graphics graphics, string beginError)
        {
            graphics.Clear(System.Drawing.Color.CornflowerBlue);

            using (Brush brush = new SolidBrush(System.Drawing.Color.Black))
            {
                using (StringFormat format = new StringFormat())
                {
                    format.Alignment = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;

                    graphics.DrawString(beginError, Font, brush, ClientRectangle, format);
                }
            }
        }
        /// <summary>
        /// 背景の描画メッセージ処理
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //背景の描画のメッセージを無視する。
            //既定の実装では背景描画→XNAとなるので画面がちらつく。
            //その為、背景を描画しないようにする。
            //base.OnPaintBackground(e);
        }
    }
}
