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 Headlinear : IDisposable
    {
        #region 定数値

        /// <summary>
        /// スケーリングする値の定義
        /// </summary>
        protected const float RATE_SCALER = 128.0f;

        #endregion

        #region フィールドメンバ

        protected bool init;
        protected bool finish;
        protected bool useSprite;	//!< スプライトで描画を行うか？
        protected bool m_reverse;


        // 表示スタイルの指定
        protected int styleType;

        protected int m_disposeStep;	//!< 処理が終了するまでのステップ

        protected int m_interval;		//!< 次の文字を表示するまでの休止フレーム

        protected int intervalCount;
        protected int drawCount;

        protected int moveX;	//!< 移動量X
        protected int moveY;	//!< 移動量X

        protected int topMargin;
        protected int leftMargin;
        protected int bottomMargin;
        protected int rightMargin;

        protected List<int> vx;	//!< 表示位置の列
        protected List<int> vy;
        protected List<RootCounterS> vAlpha;	//!< テクスチャのα値
        protected List<InteriorCounter> vRate;	//!< テクスチャの拡大レート値 RATE_SCALER でスケーリングしてある
        protected List<InteriorCounter> vMoveX;	//!< 移動X
        protected List<InteriorCounter> vMoveY;	//!< 移動Y
        protected List<InteriorCounter> vRotation;	//!< 回転角
        protected List<bool> roteFinish;	//!< 各テクスチャの移動終了フラグ

        protected List<ITexture> vt;	//!< 表示していくテクスチャ列
        //protected Sprite.SpriteVector sv;	//!< 表示する文字列のスプライト情報

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Headlinear()
        {
            vx = new List<int>();
            vy = new List<int>();
            vAlpha = new List<RootCounterS>();
            vRate = new List<InteriorCounter>();
            vMoveX = new List<InteriorCounter>();
            vMoveY = new List<InteriorCounter>();
            vRotation = new List<InteriorCounter>();
            vt = new List<ITexture>();
            roteFinish = new List<bool>();
        }

        /// <summary>
        /// 表示スタイルを設定する
        /// </summary>
        /// <param name="style"></param>
        public void SetStyle(int style)
        {
            if (styleType != style)
            {
                styleType = style;
                init = false;
                IsFinish = false;
            }
        }

        /// 移動量を設定します
        public void SetMoveXY(int x_, int y_)
        {
            moveX = x_;
            moveY = y_;
        }

        /// 移動量を取得します
        public void GetMoveXY(out int x_, out int y_)
        {
            x_ = moveX;
            y_ = moveY;
        }


        /// <summary>
        /// 文字と文字との インターバルの設定
        /// これで総合的な描画速度が決まる
        /// </summary>
        public int Interval
        {
            get { return m_interval; }
            set { m_interval = value; }
        }

        /// <summary>
        /// 最後尾から描画を始めるか
        /// </summary>
        public bool Reverse
        {
            get { return m_reverse; }
            set { m_reverse = value; }
        }

        /// <summary>
        /// 特殊描画処理のステップ数
        /// </summary>
        public int DisposeStep
        {
            get { return m_disposeStep; }
            set { m_disposeStep = value; }
        }

        /// <summary>
        /// ロードされたテクスチャを追加します
        /// </summary>
        /// <param name="t_"></param>
        public void AddTexture(ITexture t_)
        {
            vt.Add(t_);

            // 属性も増やしとく
            vx.Add(0);
            vy.Add(0);
            vAlpha.Add(new RootCounterS(0, 255, 1));
            vRate.Add(new InteriorCounter());
            vMoveX.Add(new InteriorCounter(0, 0, 1));	// 無効にしとく
            vMoveY.Add(new InteriorCounter(0, 0, 1));	// 無効にしとく
            vRotation.Add(new InteriorCounter());
            roteFinish.Add(false);
        }

        /// 余白を設定します
        public void SetMargin(int top, int left, int right, int bottom)
        {
            topMargin = top;
            leftMargin = left;
            bottomMargin = bottom;
            rightMargin = right;
        }

        /// 全オブジェクトの描画アルファを設定します
        public void SetAlphaCounterAll(int start, int end, int step)
        {
            foreach (RootCounterS c in vAlpha)
            {
                c.Set(start, end, step);
            }
        }

        public bool IsFinish
        {
            get { return finish; }
            set { finish = value; }
        }

        /// テクスチャと属性のクリア
        public virtual void Clear()
        {
            vt.Clear();
            vx.Clear();
            vy.Clear();
            vAlpha.Clear();
            vRate.Clear();
            vMoveX.Clear();
            vMoveY.Clear();
            vRotation.Clear();
            useSprite = false;
            init = false;
            finish = false;
            drawCount = 0;
            moveX = 0;
            moveY = 0;
            topMargin = 0;
            leftMargin = 0;
            bottomMargin = 0;
            rightMargin = 0;
            //sv = null;
            roteFinish.Clear();
        }

        /// 描画
        public abstract void OnDraw(IScreen screen);

        /// 描画結果をもらう
        public virtual void OnDraw(out Textures tv)
        {
            tv = null;
        }

        /// 連結後の仮想座標位置の取得
        public virtual void GetXY(out int x_, out int y_)
        {
            x_ = y_ = 0;
        }

        #region IDisposable メンバ

        public void Dispose()
        {
        }

        #endregion
    }

    /// <summary>
    /// タイトルテロップ等での表題表示を行います
    /// 不透明度をさげながらなめらかにスライドインしてから定常描画します
    /// </summary>
    public class SlideInHeadlinear : Headlinear
    {
        #region 定数値


        #endregion

        #region フィールドメンバ

        private readonly SinTable sin = SinTable.Instance;	//!< 移動量制御用
        private int x;	//!< 描画位置X
        private int y;	//!< 描画位置Y
        private bool fadeOut;	//!< フェードアウトさせるか

        #endregion

        /// 表示位置の設定
        public void SetXY(int x_, int y_)
        {
            x = x_;
            y = y_;
        }

        /// 処理完了後にフェードアウトさせるか
        public void SetFadeOut(bool b_)
        {
            fadeOut = b_;
        }

        /// 描画位置の取得
        public override void GetXY(out int x_, out int y_)
        {
            x_ = y_ = 0;
            if (finish)
            {
                int i = 0, posx, posy, minX = int.MaxValue, minY = int.MaxValue;
                foreach (ITexture t in vt)
                {
                    posx = vx[i] + moveX;
                    posy = vy[i] + moveY;
                    if (posx < minX)
                    {
                        minX = posx;
                    }
                    if (posy < minY)
                    {
                        minY = posy;
                    }
                    i++;
                }
                x_ = minX;
                y_ = minY;
            }
        }

        /// <summary>
        /// 毎回呼び出すなり
        /// </summary>
        /// <param name="screen"></param>
        public override void OnDraw(IScreen screen)
        {
            // 設定してからにしてくれ
            if (vt.Count == 0) return;

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

            int posx, posy;
            if (!finish)
            {
                intervalCount++;
                if (intervalCount >= m_interval)
                {
                    intervalCount = 0;
                    drawCount++;
                }

                // インクリメント
                int i, j = 0;
                if (m_reverse)
                {
                    for (i = vAlpha.Count - 1; i >= 0; --i)
                    {
                        if (j > drawCount) break;

                        vAlpha[i]++;
                        vRotation[i]++;

                        // フェードアウト処理設定
                        if (fadeOut && vRotation[i].IsEnd && !roteFinish[i])
                        {
                            roteFinish[i] = true;
                            int alphaNow = vAlpha[i].Value();
                            vAlpha[i].Set(alphaNow, 0, 2);
                        }
                        j++;
                    }

                    // 描画
                    for (i = vAlpha.Count - 1; i >= 0; --i)
                    {
                        if (j > drawCount) break;

                        screen.SetColor(255, 255, 255, vAlpha[i].Value());

                        posx = vx[i] + sin.Sin(vRotation[i].Value(), moveX);
                        posy = vy[i] + sin.Sin(vRotation[i].Value(), moveY);

                        screen.Blt(vt[i], posx, posy);
                        j++;
                    }

                }
                else
                {	// !IsReverse

                    // 各カウンタの増分
                    for (i = 0; i < vAlpha.Count; ++i)
                    {
                        if (i > drawCount) break;

                        vAlpha[i]++;
                        vRotation[i]++;

                        // フェードアウト処理設定
                        if (fadeOut && vRotation[i].IsEnd && !roteFinish[i])
                        {
                            roteFinish[i] = true;
                            int alphaNow = vAlpha[i].Value();
                            vAlpha[i].Set(alphaNow, 0, 2);
                        }
                    }

                    // 描画
                    j = 0;
                    foreach (ITexture t in vt)
                    {
                        if (j > drawCount) break;

                        screen.SetColor(255, 255, 255, vAlpha[j].Value());

                        posx = vx[j] + sin.Sin(vRotation[j].Value(), moveX);
                        posy = vy[j] + sin.Sin(vRotation[j].Value(), moveY);

                        screen.Blt(t, posx, posy);
                        ++j;
                    }
                }
            }
            else if (!fadeOut)
            {
                // 定常描画
                int i = 0;
                foreach (ITexture t in vt)
                {
                    posx = vx[i] + moveX;
                    posy = vy[i] + moveY;
                    screen.Blt(t, posx, posy);
                    i++;
                }
            }

            // エフェクトおわったんか？
            for (int i = vAlpha.Count - 1; i >= 0; --i)
            {
                if (!vAlpha[i].IsEnd)
                {
                    break;
                }
                finish = true;
            }

            screen.ResetColor();
        }


        #region 非公開メンバ

        /// <summary>
        /// 初期化処理
        /// </summary>
        /// <param name="screen"></param>
        void OnInit(IScreen screen)
        {
            int size = vt.Count;	// テクスチャの数
            int sunWidth = 0;	// 全テクスチャの連結幅
            int maxHeight = 0;	// 一番高いテクスチャの高さ
            int maxWidth = 0;	// 一番幅が広いテクスチャの幅

            foreach (ITexture t in vt)
            {
                int height = int.MinValue;
                int width = int.MinValue;
                width = (int)t.Width;
                height = (int)t.Height;

                sunWidth += width;

                if (maxWidth < width)
                {
                    maxWidth = width;
                }

                if (maxHeight < height)
                {
                    maxHeight = height;
                }
            }

            int tWidth = 0;
            int tHeight;
            int offsetX = x;
            int offsetY = y;
            int adjustY;

            int i = 0;
            foreach (ITexture t in vt)
            {
                // 一つ前のテクスチャの幅に合わせてずらしていく
                offsetX += tWidth;

                tWidth = (int)t.Width;
                tHeight = (int)t.Height;

                if (tHeight != maxHeight)
                {
                    adjustY = (maxHeight - tHeight) / 2;
                }
                else
                {
                    adjustY = 0;
                }

                vx[i] = offsetX;
                vy[i] = offsetY + adjustY;

                vAlpha[i].Set(0, 255, 3);

                vRotation[i].Set(0, 128, m_disposeStep);
                ++i;
            }
        }

        #endregion
    }

    public class SequentialDrawAlpha : Headlinear
    {

        #region フィールドメンバ

        private int x;
        private int y;
        private int rateStep;
        private float startRate = 0.0f;

        #endregion

        /// <summary>
        /// 表示開始時の拡大レート
        /// </summary>
        public float StartRate
        {
            get { return startRate; }
            set { startRate = value; }
        }

        /// <summary>
        /// 縮小エフェクトフレーム数の設定
        /// </summary>
        /// <param name="step"></param>
        public void SetEffectingFrame(int step)
        {
            if (0 >= step)
            {
                step = 1;
            }
            rateStep = step;
        }

        /// <summary>
        /// 描画位置の設定
        /// </summary>
        /// <param name="x_"></param>
        /// <param name="y_"></param>
        public void SetXY(int x_, int y_)
        {
            x = x_;
            y = y_;
        }

        /// <summary>
        /// 描画位置の取得
        /// </summary>
        /// <param name="x_"></param>
        /// <param name="y_"></param>
        public override void GetXY(out int x_, out int y_)
        {
            x_ = x;
            y_ = y;
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="screen"></param>
        public override void OnDraw(IScreen screen)
        {
            if (!init)
            {
                OnInit(screen);
                init = true;
            }

            if ((drawCount < vt.Count) && (intervalCount++ >= m_interval))
            {
                intervalCount = 0;
                drawCount++;
            }

            int i = 0;
            foreach (ITexture t in vt)
            {

                if (drawCount == i) break;

                if (!roteFinish[i])
                {
                    vRate[i]++;
                    vAlpha[i]++;

                    float fRate = (float)vRate[i].Value() / RATE_SCALER;
                    screen.SetColor(255, 255, 255, vAlpha[i].Value());
                    screen.BltRotate(t, x, y, 0, fRate, 4);	// 描画

                    if (vRate[i].IsEnd && vAlpha[i].IsEnd)
                    {
                        roteFinish[i] = true;
                    }
                }
                ++i;
            }

            i = 0;
            for (i = 0; i < roteFinish.Count; ++i)
            {
                if (!roteFinish[i]) break;
            }

            if (i == roteFinish.Count)
            {
                finish = true;
            }
        }


        #region 非公開メンバ

        /// <summary>
        /// 初期化処理
        /// </summary>
        /// <param name="screen"></param>
        private void OnInit(IScreen screen)
        {
            // テクスチャの数
            int size = vt.Count;

            for (int i = 0; i < size; ++i)
            {
                // α値
                vAlpha[i].Set(200, 0, 5);
                vRate[i].Set((int)(StartRate * RATE_SCALER), (int)(0.8f * RATE_SCALER), rateStep);
            }
        }

        #endregion
    }

    /// <summary>
    ///  タイトルテロップ等での表題表示を行います
    /// 不透明度をげながら拡大された状態から縮小された状態に移行します
    /// </summary>
    public class ReduceHeadlinear : Headlinear
    {
        #region 定数値

        /// <summary>
        /// 表示スタイルの定義
        /// </summary>
        public enum Style : int { LEFT, CENTER, RIGHT, TOP_LEFT, BOTTM_LEFT, TOP_RIGHT, BOTTOM_RIGHT };

        #endregion

        #region フィールドメンバ

        private Rand rand;
        private float startRate;
        private bool fadeOut;
        private bool nowFade;
        //private int alphaStep;
        private int rateStep;
        private bool randMove;	//!< 指定されているmoveX,moveYをランダムに設定するか？
        private bool useUserPos;
        private int posx = int.MinValue;
        private int posy = int.MinValue;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public ReduceHeadlinear()
            : base()
        {
            rand = new Rand();
            rand.Randomize();
            startRate = 5;	// 5ぐらい？
            rateStep = 128;	// 128で拡大終了
        }


        /// 表示位置を自分できめる
        public void SetXY(int x, int y)
        {
            posx = x;
            posy = y;
            useUserPos = true;
        }

        public void SetRandomMove(bool b)
        {
            randMove = b;
        }

        /// 縮小エフェクトフレーム数の設定
        public void SetEffectingFrame(int step)
        {
            if (0 >= step)
            {
                step = 1;
            }
            rateStep = step;
        }

        /// フェードアウトするかどうか？
        public void SetFadeOut(bool b_)
        {
            fadeOut = true;
        }

        /// 表示開始時の拡大レート
        public void SetStartRate(float rate_)
        {
            startRate = rate_;
        }

        public override void OnDraw(IScreen screen)
        {
            // 設定してからにしてくれ
            if (vt.Count == 0) return;

            if (!init)
            {
                // スタイルから属性を設定する
                if (!useSprite)
                {
                    OnInit(screen);
                }
                else
                {
                    //onInitWithSprite(screen);
                }
            }

            if (!finish)
            {
                intervalCount++;
                if (intervalCount >= Interval)
                {
                    intervalCount = 0;
                    drawCount++;
                }

                // インクリメント
                if (Reverse)
                {
                    int j = 0;
                    for (int i = vAlpha.Count - 1; i >= 0; --i)
                    {
                        if (j > drawCount) break;
                        vAlpha[i]++;
                        vRate[i]++;
                        vMoveX[i]++;
                        vMoveY[i]++;
                        j++;
                    }
                }
                else
                {
                    for (int i = 0; i < vAlpha.Count; ++i)
                    {
                        if (i > drawCount) break;
                        vAlpha[i]++;
                        vRate[i]++;
                        vMoveX[i]++;
                        vMoveY[i]++;
                    }
                }
            }

            // 描画完了して、フェードアウトであれば描画することはない
            if (!(finish && fadeOut))
            {
                if (!useSprite)
                {
                    OnDrawTextures(screen);
                }
                else
                {
                    //onDrawSprite(screen);
                }
            }

            // エフェクトおわったんか？
            if (!finish)
            {
                if (Reverse)
                {
                    for (int i = 0; i < vAlpha.Count; ++i)
                    {
                        if (!vAlpha[i].IsEnd || !vRate[i].IsEnd
                           || !vMoveX[i].IsEnd || !vMoveX[i].IsEnd)
                        {
                            break;
                        }
                        if (fadeOut && !nowFade)
                        {
                            foreach (RootCounterS c in vAlpha)
                            {
                                c.Set(255, 0, 4);
                            }
                            nowFade = true;
                        }
                        else
                        {
                            finish = true;
                        }
                    }
                }
                else
                {
                    for (int i = vAlpha.Count - 1; i >= 0; --i)
                    {
                        if (!vAlpha[i].IsEnd || !vRate[i].IsEnd
                           || !vMoveX[i].IsEnd || !vMoveX[i].IsEnd)
                        {
                            break;
                        }

                        if (fadeOut && !nowFade)
                        {
                            foreach (RootCounterS c in vAlpha)
                            {
                                c.Set(255, 0, 4);
                            }
                            nowFade = true;
                        }
                        else
                        {
                            finish = true;
                        }
                    }
                }
            }
        }

        /// 表示位置の取得
        public override void GetXY(out int x_, out int y_)
        {
            x_ = y_ = 0;
            if (finish)
            {
                int i = 0, x, y, minX = int.MaxValue, minY = int.MaxValue;
                if (!useSprite)
                {
                    //foreach (ITexture t in vt)
                    //{
                    //    // 座標の中心に描画されとる
                    //    x = vx[i] - (int)t.Width / 2;
                    //    y = vy[i] - (int)t.Height / 2;
                    //    if (x < minX)
                    //    {
                    //        minX = x;
                    //    }
                    //    if (y < minY)
                    //    {
                    //        minY = y;
                    //    }
                    //    i++;
                    //}

                    foreach (ITexture s in vt)
                    {
                        // 座標の中心に描画されとる
                        x = vx[i];//-(int)s.rcRect.Width/2;
                        y = vy[i];//-(int)s.rcRect.Height/2;
                        if (x < minX)
                        {
                            minX = x;
                        }
                        if (y < minY)
                        {
                            minY = y;
                        }
                        i++;
                    }

                }
                else
                {
                    //foreach(inout SimpleSprite s;sv) {
                    //    // 座標の中心に描画されとる
                    //    x = vx[i];//-(int)s.rcRect.Width/2;
                    //    y = vy[i];//-(int)s.rcRect.Height/2;
                    //    if (x<minX) {
                    //        minX = x;
                    //    }
                    //    if (y<minY) {
                    //        minY = y;
                    //    }
                    //    i++;
                    //}
                }
                x_ = minX;
                y_ = minY;
            }
        }

        // 初期化
        public override void Clear()
        {
            base.Clear();
            useUserPos = false;
        }

        #region 非公開メンバ

        /// <summary>
        /// テクスチャの列から描画する
        /// </summary>
        /// <param name="screen"></param>
        private void OnDrawTextures(IScreen screen)
        {

            // 描画
            int x;
            int y;
            int alpha;
            float rate = 1.0f;

            screen.BlendSrcAlpha();

            if (!finish)
            {
                if (Reverse)
                {
                    int i, j = 0;
                    for (i = vt.Count - 1; i >= 0; --i)
                    {
                        if (j > drawCount) break;

                        int offsetx = vMoveX[i].Value();
                        int offsety = vMoveY[i].Value();

                        x = vx[i] + offsetx;
                        y = vy[i] + offsety;
                        alpha = vAlpha[i].Value();
                        rate = (vRate[i].Value() / RATE_SCALER);	// スケーリング戻し

                        screen.SetColor(255, 255, 255, alpha);
                        screen.BltRotate(vt[i], x, y, (Rect)null, 0, rate, 0, 0);	// 描画
                        j++;
                    }
                }
                else
                {
                    for (int i = 0; i < vt.Count; i++)
                    {
                        if (i > drawCount) break;

                        int offsetx = vMoveX[i].Value();
                        int offsety = vMoveY[i].Value();

                        x = vx[i] + offsetx;
                        y = vy[i] + offsety;
                        alpha = vAlpha[i].Value();
                        rate = (vRate[i].Value() / RATE_SCALER);	// スケーリング戻し

                        screen.SetColor(255, 255, 255, alpha);
                        screen.BltRotate(vt[i], x, y, (Rect)null, 0, rate, 0, 0);	// 描画
                    }

                }
            }
            else
            {
                for (int i = 0; i < vt.Count; i++)
                {
                    x = vx[i];
                    y = vy[i];
                    screen.SetColor(255, 255, 255);
                    screen.Blt(vt[i], x, y);	// 描画
                }
            }

            screen.ResetColor();
        }


        //private void onDrawSprite(IScreen screen)
        //{
        //    //// 描画
        //    //int x;
        //    //int y;
        //    //int alpha;
        //    //float rate = 1.0f;

        //    //screen.blendSrcAlpha();

        //    //if (!finish) {
        //    //    if (reverse) {
        //    //        int i,j;
        //    //        for (i = sv.length-1; i>=0; --i) {
        //    //            if (j > drawCount) break;

        //    //            int offsetx = vMoveX[i].get();
        //    //            int offsety = vMoveY[i].get();

        //    //            x = vx[i] + offsetx;
        //    //            y = vy[i] + offsety;
        //    //            alpha = vAlpha[i].get();
        //    //            rate = (vRate[i].get()/RATE_SCALER);	// スケーリング戻し

        //    //            screen.setColor(255,255,255,alpha);
        //    //            screen.bltRotate(sv[i].texture,x,y,&sv[i].rcRect,0,rate,0,0);	// 描画
        //    //            j++;
        //    //        }
        //    //    } else {
        //    //        foreach(int i,inout SimpleSprite s; sv) {
        //    //            if (i > drawCount) break;

        //    //            int offsetx = vMoveX[i].get();
        //    //            int offsety = vMoveY[i].get();

        //    //            x = vx[i] + offsetx;
        //    //            y = vy[i] + offsety;
        //    //            alpha = vAlpha[i].get();
        //    //            rate = (vRate[i].get()/RATE_SCALER);	// スケーリング戻し

        //    //            screen.setColor(255,255,255,alpha);
        //    //            screen.bltRotate(s.texture,x,y,&s.rcRect,0,rate,0,0);	// 描画
        //    //        }
        //    //    }
        //    //} else {
        //    //    foreach(int i,inout SimpleSprite s; sv) {
        //    //        x = vx[i];
        //    //        y = vy[i];
        //    //        screen.setColor(255,255,255);
        //    //        screen.blt(s.texture,x,y,&s.rcRect);	// 描画
        //    //    }
        //    //}

        //    //screen.resetColor();
        //}

        /// <summary>
        /// 初期化処理
        /// </summary>
        /// <param name="screen"></param>
        private void OnInitTexture(IScreen screen)
        {
            init = true;
            drawCount = 0;

            // 画面サイズ
            int screenX = screen.Width;
            int screenY = screen.Height;

            int size = vt.Count;	// テクスチャの数
            int sumWidth = 0;	// 全テクスチャの連結幅
            int maxHeight = 0;	// 一番高いテクスチャの高さ
            int maxWidth = 0;	// 一番幅が広いテクスチャの幅

            foreach (ITexture t in vt)
            {
                int height;
                int width;
                width = (int)t.Width;
                height = (int)t.Height;

                sumWidth += width;

                if (maxWidth < width)
                {
                    maxWidth = width;
                }

                if (maxHeight < height)
                {
                    maxHeight = height;
                }
            }

            // そのテクスチャのサイズ
            int tWidth = 0;
            int tHeight = 0;
            // 表示位置
            int x, y;
            int offsetX, offsetY;
            int adjustX, adjustY;

            switch ((Style)styleType)
            {
                case Style.LEFT:	// 左寄せ
                    {
                        int i = 0;
                        offsetX = leftMargin;
                        offsetY = (screenY - maxHeight) / 2;

                        foreach (ITexture t in vt)
                        {
                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.CENTER:	// センタリング
                    {
                        int i = 0;

                        if (useUserPos)
                        {
                            offsetX = posx;
                            offsetY = posy;
                        }
                        else
                        {
                            offsetX = (screenX - sumWidth) / 2;//+(sumWidth/vt.size())/2;
                            offsetY = (screenY - maxHeight) / 2;
                        }
                        foreach (ITexture t in vt)
                        {
                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            vMoveX[i].Set(moveX, 0, rateStep);
                            vMoveY[i].Set(moveY, 0, rateStep);

                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.RIGHT:	// 右寄せ
                    {
                        int i = 0;
                        offsetX = (screenX - rightMargin) + sumWidth;
                        offsetY = (screenY - maxHeight) / 2;

                        foreach (ITexture t in vt)
                        {
                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.TOP_LEFT:	// 左上寄せ
                    {
                        int i;
                        offsetX = (maxWidth / 2) + leftMargin;
                        offsetY = topMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの高さを求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetY += (int)vt[i].Height;
                        }

                        // 描画位置はbottomではないので、戻しておく
                        offsetY -= (int)vt[0].Height;

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetX += tWidth;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetY -= tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                x = vx[i] = offsetX + adjustX;
                                y = vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.BOTTM_LEFT:	// 左下寄せ
                    {
                        int i;
                        offsetX = (maxWidth / 2) + leftMargin;
                        offsetY = screenY - bottomMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの高さを求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetY -= (int)vt[i].Height;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetX += tWidth;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetY += tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                x = vx[i] = offsetX + adjustX;
                                y = vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.TOP_RIGHT:	// 右上寄せ
                    {
                        int i;
                        offsetX = (screenX - rightMargin) + (maxWidth / 2);
                        offsetY = topMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの幅を求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetX -= (int)vt[i].Width;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetY += tHeight;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetY += tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                vx[i] = offsetX + adjustX;
                                vy[i] = offsetY;


                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.BOTTOM_RIGHT:	// 右下寄せ
                    {
                        int i;
                        offsetX = (screenX - rightMargin) + (maxWidth / 2);
                        offsetY = (screenY - bottomMargin) - (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの幅を求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetX -= (int)vt[i].Width;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetY -= tHeight;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetY -= tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                vx[i] = offsetX + adjustX;
                                vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                default:
                    //Log.printError("Headlinear.OnDraw:Invalid Style!\n");
                    break;
            }
        }


        private void OnInit(IScreen screen)
        {
            init = true;
            drawCount = 0;

            // 画面サイズ
            int screenX = screen.Width;
            int screenY = screen.Height;

            int size = vt.Count;	// テクスチャの数
            int sumWidth = 0;	// 全テクスチャの連結幅
            int maxHeight = 0;	// 一番高いテクスチャの高さ
            int maxWidth = 0;	// 一番幅が広いテクスチャの幅

            foreach (ITexture s in vt)
            {
                int height;
                int width;
                width = (int)s.Width;
                height = (int)s.Height;

                sumWidth += width;

                if (maxWidth < width)
                {
                    maxWidth = width;
                }

                if (maxHeight < height)
                {
                    maxHeight = height;
                }
            }

            // そのテクスチャのサイズ
            int tWidth = 0;
            int tHeight = 0;
            // 表示位置
            int x, y;
            int offsetX, offsetY;
            int adjustX, adjustY;

            switch ((Style)styleType)
            {
                case Style.LEFT:	// 左寄せ
                    {
                        int i = 0;
                        offsetX = leftMargin;
                        offsetY = (screenY - maxHeight) / 2;

                        foreach (ITexture t in vt)
                        {
                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.CENTER:	// センタリング
                    {
                        int i = 0;

                        if (useUserPos)
                        {
                            offsetX = posx;
                            offsetY = posy;
                        }
                        else
                        {
                            offsetX = (screenX - sumWidth) / 2 + (sumWidth / size) / 2;
                            offsetY = (screenY - maxHeight) / 2;
                        }
                        foreach (ITexture s in vt)
                        {
                            tWidth = (int)s.Width;
                            tHeight = (int)s.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            int mx = 0, my = 0;

                            if (randMove)
                            {
                                if (moveX != 0) mx = rand.GetRand(moveX);
                                if (rand.GetRand0_1A() < 0.0) mx = -mx;
                                if (moveY != 0) my = rand.GetRand(moveY);
                                if (rand.GetRand0_1A() < 0.0) my = -mx;
                            }
                            else
                            {
                                if (i <= size / 2)
                                {
                                    mx = moveX * ((size / 2) - i) / (size / 2);
                                }
                                else
                                {
                                    mx = moveX * ((size / 2) - i) / (size / 2);
                                }
                                my = moveY;
                            }

                            vMoveX[i].Set(mx, 0, rateStep);
                            vMoveY[i].Set(my, 0, rateStep);
                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.RIGHT:	// 右寄せ
                    {
                        int i = 0;
                        offsetX = (screenX - rightMargin) + sumWidth;
                        offsetY = (screenY - maxHeight) / 2;

                        foreach (ITexture t in vt)
                        {
                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            // 一番最初は加算しなくてええよ〜
                            if (i > 0)
                            {
                                offsetX += tWidth;
                            }

                            if (tHeight != maxHeight)
                            {
                                adjustY = (maxHeight - tHeight) / 2;
                            }
                            else
                            {
                                adjustY = 0;
                            }

                            vx[i] = offsetX;
                            vy[i] = offsetY + adjustY;

                            // カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.TOP_LEFT:	// 左上寄せ
                    {
                        int i;
                        offsetX = (maxWidth / 2) + leftMargin;
                        offsetY = topMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの高さを求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetY += (int)vt[i].Height;
                        }

                        // 描画位置はbottomではないので、戻しておく
                        offsetY -= (int)vt[0].Height;

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetX += tWidth;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetY -= tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                x = vx[i] = offsetX + adjustX;
                                y = vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.BOTTM_LEFT:	// 左下寄せ
                    {
                        int i;
                        offsetX = (maxWidth / 2) + leftMargin;
                        offsetY = screenY - bottomMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの高さを求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetY -= (int)vt[i].Height;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetX += tWidth;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetY += tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                x = vx[i] = offsetX + adjustX;
                                y = vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.TOP_RIGHT:	// 右上寄せ
                    {
                        int i;
                        offsetX = (screenX - rightMargin) + (maxWidth / 2);
                        offsetY = topMargin + (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの幅を求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetX -= (int)vt[i].Width;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetY += tHeight;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetY += tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                vx[i] = offsetX + adjustX;
                                vy[i] = offsetY;


                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                case Style.BOTTOM_RIGHT:	// 右下寄せ
                    {
                        int i;
                        offsetX = (screenX - rightMargin) + (maxWidth / 2);
                        offsetY = (screenY - bottomMargin) - (maxHeight / 2);

                        // 折り返し位置
                        int turnPos = vt.Count / 2;

                        // 折り返し地点までの幅を求める
                        for (i = 0; i < turnPos; ++i)
                        {
                            offsetX -= (int)vt[i].Width;
                        }

                        i = 0;
                        foreach (ITexture t in vt)
                        {
                            if (i == turnPos)
                            {
                                offsetY -= tHeight;
                            }

                            tWidth = (int)t.Width;
                            tHeight = (int)t.Height;

                            if (i < turnPos)
                            {
                                if (i > 0)
                                {
                                    offsetX += tWidth;
                                }

                                if (tHeight != maxHeight)
                                {
                                    adjustY = (maxHeight - tHeight) / 2;
                                }
                                else
                                {
                                    adjustY = 0;
                                }

                                vx[i] = offsetX;
                                vy[i] = offsetY + adjustY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }
                            else
                            {
                                // 折り返し最初は加算しなくてええよ〜
                                if (i != turnPos)
                                {
                                    offsetY -= tHeight;
                                }

                                if (tWidth != maxWidth)
                                {
                                    adjustX = (maxWidth - tWidth) / 2;
                                }
                                else
                                {
                                    adjustX = 0;
                                }

                                vx[i] = offsetX + adjustX;
                                vy[i] = offsetY;

                                vMoveX[i].Set(moveX, 0, rateStep);
                                vMoveY[i].Set(moveY, 0, rateStep);
                            }

                            // 基本カウンタの設定
                            SetBasicCounter(i);
                            ++i;
                        }
                    }
                    break;
                default:
                    //Log.printError("Headlinear.OnDraw:Invalid Style!\n");
                    break;
            }
        }

        /// <summary>
        /// 基本カウンタを設定する
        /// </summary>
        /// <param name="index"></param>
        private void SetBasicCounter(int index)
        {
            // ちゃんと設定しとけー
            if (vAlpha.Count <= index) return;

            int step = 255 / rateStep;
            if ((255 % rateStep) != 0)
            {
                step++;
            }

            if (step <= 0)
            {
                step = 1;
            }

            // アルファカウンタ
            vAlpha[index].Set(0, 255, step);

            // 拡大レートカウンタ（スケーリング
            int startRate = 0;
            startRate = (int)(startRate * RATE_SCALER);
            int endRate = (int)(1 * RATE_SCALER);
            vRate[index].Set(startRate, endRate, rateStep);
        }


        #endregion


    }
}
