using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.Draw;
using Yamalib.Util;
using Yanesdk.Math;

namespace Yamalib.Draw.Effect
{

    /// <summary>
    /// フラッシュインテキストの基本機能とインターフェースを提供します
    /// </summary>
    public abstract class FlashInObjectBase
    {
        #region 定数値

        protected static int FLASH_TIME = 8;
        protected const int RAND_SIZE = 100;
        protected const int TEXT_MOVE = -10;
        protected const int TEXT_FLASH_ALPHA = 10;

        #endregion

        #region フィールドメンバ
        protected static readonly Rand rand = new Rand();
        protected bool finish;	//!< 設定された描画が完了したか

        protected readonly List<RootCounterS> counters = new List<RootCounterS>();	//!< 文字列移動カウンタ
        protected readonly List<int> posy = new List<int>();				//!< 表示文字列のy値

        private ITexture flash;	//!< 真っ白のテクスチャ

        private ITexture textFlash;	//!< テキスト用の白フラッシュ画像

        protected RootCounterS alphaBG;
        protected RootCounterS alpha;	//!< アルファ値
        protected int alphaStep = 2;

        protected bool pluse;

        protected int showCount;	//!< 表示している文字列の数

        protected int counter;

        protected int speedCounter;
        protected int speed;		//!< 表示速度

        #endregion

        public abstract void OnMove(IScreen screen);

        public abstract void OnDraw(IScreen screen);

        /// <summary>
        /// 画面全体をフラッシュしているか
        /// </summary>
        public bool IsNowFlashBG
        {
            get { return counter <= FLASH_TIME; }
        }

        /// <summary>
        /// 終了したか
        /// </summary>
        public bool IsFinish
        {
            get { return finish; }
        }

        /// <summary>
        /// テキストをカバーするフラッシュ画像
        /// 文字サイズにあわない場合、拡縮される
        /// </summary>
        public ITexture WhiteTexture
        {
            get { return textFlash; }
            set { textFlash = value; }
        }

        /// <summary>
        /// 事前に背景真っ白のテクスチャを登録しておくこと
        /// </summary>
        public ITexture WhileTextureBG
        {
            get { return flash; }
            set { flash = value; }
        }

        /// <summary>
        /// テキスト表示速度の設定
        /// </summary>
        public int ShowSpeed
        {
            get { return speed; }
            set { speed = value; }
        }

        /// <summary>
        /// リセット
        /// </summary>
        public virtual void Reset()
        {
            counters.Clear();
            posy.Clear();
        }

    }

    /// <summary>
    /// 文字列から生成したテクスチャでフラッシュインテキストを実装します
    /// </summary>
    public class FlashInText : FlashInObjectBase
    {
        #region 定数値


        #endregion

        #region フィールドメンバ

        private bool init = false;	//!< 初期化フラグ
        private FontRepository fr;	//!< 文字貯蔵庫
        private Textures tv;	//!< 文字列を受け取る
        private readonly List<string> texts = new List<string>();	//!< 表示文字列

        #endregion

        public FlashInText()
            : base()
        {
            fr = new FontRepository(YamalibConst.FONT_REP_TEXTURE_FACTORY);
            alpha = new RootCounterS();
            alphaBG = new RootCounterS();
            speed = 30;
            counter = 0;
        }

        /// <summary>
        /// 事前に FontLoader を喰わせておくこと
        /// </summary>
        public FontRepository FontRepository
        {
            get { return fr; }
            set { fr = value; }
        }

        /// <summary>
        /// テキストの追加
        /// </summary>
        /// <param name="str"></param>
        public void AddText(string str)
        {
            if (str != null)
                texts.Add(str);
        }


        /// <summary>
        /// リセット
        /// </summary>
        public override void Reset()
        {
            base.Reset();
            init = false;
        }

        /// <summary>
        /// 事前にテクスチャを生成
        /// </summary>
        public void Update()
        {
            OnInit();
            init = true;
        }

        /// <summary>
        /// 動作の処理
        /// </summary>
        /// <param name="screen"></param>
        public override void OnMove(IScreen screen)
        {
            if (finish) return;

            if (!init)
            {
                OnInit();
                init = true;
            }

            counter++;

            if (alpha.IsEnd)
            {
                speedCounter--;
                if (speedCounter == 0)
                {
                    speedCounter = speed;
                    counter = 0;
                    alpha.Set(255, 0, TEXT_FLASH_ALPHA);

                    if (showCount + 1 == texts.Count)
                    {
                        finish = true;
                    }
                    else
                    {
                        showCount++;
                    }
                }
            }

            if (counter > FLASH_TIME)
            {
                alphaBG++;
                alpha++;

                // 文字移動
                int i = 0;
                foreach (RootCounterS c in counters)
                {
                    if (i == showCount + 1) break;
                    c++;
                    ++i;
                }
            }
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="screen"></param>
        public override void OnDraw(IScreen screen)
        {
            int i;
            int sx = screen.Width;
            int sy = screen.Height;

            if ((counter < FLASH_TIME) && !finish)
            {
                Color4ub color = YanesdkUtil.GetNowScreenColor(screen);
                screen.SetColor(255, 255, 255, 255);
                screen.DrawPolygon(
                    0, 0,
                    sx, 0,
                    sx, sy,
                    0, sy);
                screen.SetColor(color);
                return;
            }
            else
            {
                if (!alphaBG.IsEnd)
                {
                    screen.SetColor(255, 255, 255, alphaBG.Value());
                    screen.Blt(WhileTextureBG, 0, 0);
                }
            }

            if ((counter > FLASH_TIME) || finish)
            {
                screen.SetColor(255, 255, 255, 255);
                for (i = 0; i <= showCount; ++i)
                {
                    tv = fr.GetTexture(texts[i], 0);
                    screen.Blt(tv, counters[i].Value(), posy[i]);
                }

                // テキストカバーフラッシュ
                if (!alpha.IsEnd && !finish)
                {
                    int ty = (int)tv.Height;
                    screen.SetColor(255, 255, 255, alpha.Value());
                    screen.DrawPolygon(
                        0, posy[showCount],
                        sx, posy[showCount],
                        sx, posy[showCount] + ty,
                        0, posy[showCount] + ty);
                }
            }
        }

        #region 非公開メンバ

        /// 初期化処理
        private void OnInit()
        {
            posy.Clear();
            counters.Clear();
            alpha.Set(255, 0, TEXT_FLASH_ALPHA);
            alphaBG.Set(0, 255, 12);

            speedCounter = speed;
            int textNum = texts.Count;

            int offsety = 100;
            for (int i = 0; i < textNum; ++i)
            {
                posy.Add(offsety);
                offsety += (280 / textNum);

                // textureサイズを調べてセンタリングする
                tv = FontRepository.GetTexture(texts[i], 0);
                int pos = 320 - ((int)tv.Width / 2);
                pluse = !pluse;
                RootCounterS counter = new RootCounterS();
                if (pluse)
                {
                    counter.Set(pos, int.MaxValue, TEXT_MOVE);
                }
                else
                {
                    counter.Set(pos, int.MinValue, TEXT_MOVE);
                }
                counters.Add(counter);
            }
        }

        #endregion

    }
}
