namespace Background {

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using Plugin;

    public class Background : IPlugin {

        public void ApplyLanguage( string language_code ) {

        }

        /// <summary>
        /// プラグインの名称
        /// </summary>
        public string Name {
            get {
                return "Background";
            }
        }

        /// <summary>
        /// プラグインのタイプを表す。
        /// </summary>
        public ulong Type {
            get {
                return Constants.LS_ENABLES_ENTRY_SETTING + Constants.LS_NO_EVENT_HANDLER;
            }
        }

        /// <summary>
        /// プラグインの簡潔な説明文。
        /// </summary>
        public string Abstract {
            get {
                return "画像を配置するプラグインです。様々な特効が使えます。";
            }
        }

        /// <summary>
        /// イベントハンドラ。このプラグインの設定メニューが押された時呼び出されます。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public DialogResult BaseSetting() {
            return DialogResult.Cancel;
        }

        public DialogResult EntrySetting( ref string config ) {
            EntryConfig cfg = new EntryConfig( config );
            DialogResult result;
            using ( entry_config dlg = new entry_config( cfg ) ) {
                result = dlg.ShowDialog();
                if ( result == DialogResult.OK ) {
                    cfg = dlg.Config;
                    config = cfg.ToString();
                }
            }
            return result;
        }

        /// <summary>
        /// 設定値を格納した文字列を指定します。
        /// </summary>
        /// <returns></returns>
        public string Config {
            get {
                return "";
            }
            set {
            }
        }

        private Bitmap m_bmp;
        private string m_last_file = "";

        /// <summary>
        /// フレームに加工を施す関数
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="time"></param>
        public void Apply( ref Bitmap bmp, float time, float e_begin, float e_end, ref string e_body ) {
            EntryConfig cfg = new EntryConfig( e_body );
            if ( m_last_file != "" ) {
                if ( m_last_file != cfg.File ) {
                    Image img = ImageFromFile( cfg.File );
                    if ( img != null ) {
                        m_bmp = new Bitmap( img.Width, img.Height, PixelFormat.Format32bppArgb );
                        using ( Graphics gx = Graphics.FromImage( m_bmp ) ) {
                            gx.DrawImage( img, 0, 0, img.Width, img.Height );
                        }
                    }
                    m_last_file = cfg.File;
                }
            } else {
                Image img = ImageFromFile( cfg.File );
                if ( img != null ) {
                    m_bmp = new Bitmap( img.Width, img.Height, PixelFormat.Format32bppArgb );
                    using ( Graphics gx = Graphics.FromImage( m_bmp ) ) {
                        gx.DrawImage( img, 0, 0, img.Width, img.Height );
                    }
                }
            }
            float alpha = 1f;
            if ( cfg.FadeIn ) {
                float diff = time - e_begin;
                if ( 0f <= diff && diff <= cfg.FadeInRatio ) {
                    alpha = 1.0f / cfg.FadeInRatio * diff;
                }
            }
            if ( cfg.FadeOut ) {
                float diff = e_end - time;
                if ( 0f <= diff && diff <= cfg.FadeOutRatio ) {
                    alpha = 1.0f / cfg.FadeOutRatio * diff;
                }
            }
            if ( m_bmp != null ) {
                using ( Graphics g = Graphics.FromImage( bmp ) ) {
                    //g.DrawImage( m_bmp, cfg.X, cfg.Y, m_bmp.Width * cfg.Scale, m_bmp.Height * cfg.Scale );
                    ColorMatrix cm = new ColorMatrix();
                    cm.Matrix00 = 1;
                    cm.Matrix11 = 1;
                    cm.Matrix22 = 1;
                    cm.Matrix33 = alpha;
                    cm.Matrix44 = 1;
                    ImageAttributes ia = new ImageAttributes();
                    ia.SetColorMatrix( cm );

                    int width = (int)(m_bmp.Width * cfg.Scale);
                    int height = (int)(m_bmp.Height * cfg.Scale);
                    int iwidth = m_bmp.Width;
                    int iheight = m_bmp.Height;
                    g.DrawImage( m_bmp, new Rectangle( cfg.X, cfg.Y, width, height ),
                        0, 0, iwidth, iheight, GraphicsUnit.Pixel, ia );
                }
            }
        }

        /// <summary>
        /// 指定したパスのファイルからイメージを読み込みます
        /// </summary>
        /// <param name="fpath"></param>
        /// <returns></returns>
        public static Image ImageFromFile( string fpath ) {
            Image result = null;
            if ( File.Exists( fpath ) ) {
                using ( FileStream fs = new FileStream( fpath, FileMode.Open, FileAccess.Read ) ) {
                    result = Image.FromStream( fs );
                }
            }
            return result;
        }

        public void Render( Graphics g, Size size, float time, string mouth, string reserved ) {
        }
    }


    public struct EntryConfig {
        public string File;
        public bool FadeIn;
        public bool FadeOut;
        public int X;
        public int Y;
        public float Scale;
        public float FadeInRatio;
        public float FadeOutRatio;
        public EntryConfig( string config ) {
            string[] spl = config.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
            File = "";
            FadeIn = false;
            FadeOut = false;
            X = 0;
            Y = 0;
            Scale = 1f;
            FadeInRatio = 2f;
            FadeOutRatio = 2f;
            foreach ( string entry in spl ) {
                string[] spl2 = entry.Split( new char[] { '=' } );
                switch ( spl2[0] ) {
                    case "File":
                        File = spl2[1];
                        break;
                    case "FadeIn":
                        if ( spl2[1] == TRUE ) {
                            FadeIn = true;
                        } else {
                            FadeIn = false;
                        }
                        break;
                    case "FadeOut":
                        if ( spl2[1] == TRUE ) {
                            FadeOut = true;
                        } else {
                            FadeOut = false;
                        }
                        break;
                    case "X":
                        X = int.Parse( spl2[1] );
                        break;
                    case "Y":
                        Y = int.Parse( spl2[1] );
                        break;
                    case "Scale":
                        Scale = float.Parse( spl2[1] );
                        break;
                    case "FadeInRatio":
                        FadeInRatio = float.Parse( spl2[1] );
                        break;
                    case "FadeOutRatio":
                        FadeOutRatio = float.Parse( spl2[1] );
                        break;
                }
            }
        }
        private const string TRUE = "true";
        private const string FALSE = "false";
        new public string ToString() {
            string fadein, fadeout;
            if ( FadeIn ) {
                fadein = TRUE;
            } else {
                fadein = FALSE;
            }
            if ( FadeOut ) {
                fadeout = TRUE;
            } else {
                fadeout = FALSE;
            }
            return "File=" + File + "\nFadeIn=" + fadein + "\nFadeOut=" + fadeout + "\nX=" + X + "\nY=" + Y + "\nScale=" + Scale + "\nFadeInRatio=" + FadeInRatio + "\nFadeOutRatio=" + FadeOutRatio;
        }

    }
}
