using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.System;
using Kyojin.Model;
using Yanesdk.Math;
using Yanesdk.Sound;
using Yanesdk.Draw;
using Yamalib.Draw.Effect;
using Yamalib.Input;
using Yanesdk.Timer;
using Yamalib.Util;
using Yamalib;

namespace Kyojin.Scene.Ending
{
    class TrialEnding : TaskBase, IDisposable
    {
        #region 定数値

        private static bool CAP_SCREEN = true;

        private const int ROLE_Y = 80;
        private const int NAME_Y = 250;
        private const int ROLE_ALPHA_STEP = 10;
        private const int HEADLINE_INTERVAL = 15;
        private const int HEADLINE_EFFECT_TIME = 120;
        private const int HEADLINE_RATE = 10;
        private const int BREAK_WAIT = 150;
        //	private const int BREAK_WAIT = 30;

        private const int STAFF_STEP_MAX = 13;

        private const uint START_TXT_MS = 141 * 1000;	// テキストフェーズ開始ミリ秒	
        private const uint START_END_MS = 190 * 1000;	// エンドフェーズ開始ミリ秒
        private const uint START_COMMAND_MS = 176 * 1000;
        private const uint START_END_TELOP_MS = 198 * 1000;
        private const uint START_END_TASK_MS = 223 * 1000;

        enum Name : int { KOW = 0, NICHI, G9, ALICE, AMUA, SUOU, TATUWO, HAZUKI, ANZAI, HARUHI, HARA };
        enum ROLE_POS : int { SCENARIO, SCENARIO_EDIT, INTERFACE, PLAN, CREATE };
        private readonly static int[][] rolePos = new int[][]{
		  new int[]{85,112},		// シナリオ
		  new int[]{285,355},	// シナリオ演出
		  new int[]{30,80},		// インターフェース
		  new int[]{105,80},		// 企画
		  new int[]{105,345},	// 作成
	    };
        enum NAME_POS : int { SCENARIO, SCENARIO_EDIT, PLAN, CREATE };
        private static readonly int[][] namePos = new int[][]{
		  new int[]{345,132},	// シナリオ @lice
		  new int[]{55,375},		// シナリオ演出 g9
		  new int[]{300,100},	// 企画
		  new int[]{288,365},	// 作成
	    };

        private static readonly string[] SURFACE_NAME = new string[]{
		    "img/ending/bg/place12.png",
		    "img/ending/bg/place13.png",
		    "img/ending/bg/place11.png",
		    "img/ending/bg/place13.png",
		    "img/ending/bg/place15.png",
		    "img/ending/bg/place14.png",
		    "img/ending/bg/place13.png",
		    "img/ending/bg/place06.png",
		    "img/ending/bg/place05.png",
		    "img/ending/bg/place04.png",
		    "img/ending/bg/place01.png",
		    "img/ending/bg/place07.png",
		    "img/ending/bg/place08.png",
	    };

        /// 現在のＦＳＰと６０との比率
        private static int FSP_RATE = 1;

        //private static readonly string IMG__BACK__PLACE010_JPG = "img\\back\\place010.jpg";
        //private static readonly string IMG__ENDING__ALICE_PNG = "img\\ending\\alice.png";
        //private static readonly string IMG__ENDING__AMUA_PNG = "img\\ending\\amua.png";
        //private static readonly string IMG__ENDING__ANZAI_PNG = "img\\ending\\anzai.png";
        private static readonly string IMG__ENDING__BG_JPG = "img\\ending\\bg.jpg";
        private static readonly string IMG__ENDING__COMMAND_PNG = "img\\ending\\command.png";
        //private static readonly string IMG__ENDING__CREATE_PNG = "img\\endingCreatete.png";
        //private static readonly string IMG__ENDING__G9FRIED_PNG = "img\\ending\\g9fried.png";
        //private static readonly string IMG__ENDING__GRA_PNG = "img\\ending\\gra.png";
        //private static readonly string IMG__ENDING__HARUHI_PNG = "img\\ending\\haruhi.png";
        //private static readonly string IMG__ENDING__HAZUKI_PNG = "img\\ending\\hazuki.png";
        //private static readonly string IMG__ENDING__INTERFACE_PNG = "img\\ending\\interface.png";
        private static readonly string IMG__ENDING__KOWASUHITO_PNG = "img\\ending\\kowasuhito.png";
        //private static readonly string IMG__ENDING__MASK1_PNG = "img\\ending\\mask1.png";
        //private static readonly string IMG__ENDING__NAGATUKI_PNG = "img\\ending\\nagatuki.png";
        //private static readonly string IMG__ENDING__NICHINO_PNG = "img\\ending\\nichino.png";
        //private static readonly string IMG__ENDING__PLAN_PNG = "img\\ending\\plan.png";
        //private static readonly string IMG__ENDING__PROGRAM_PNG = "img\\ending\\program.png";
        //private static readonly string IMG__ENDING__ROLE_PNG = "img\\ending\\role.png";
        //private static readonly string IMG__ENDING__SATUEI_PNG = "img\\ending\\satuei.png";
        //private static readonly string IMG__ENDING__SCENARIO_PNG = "img\\ending\\scenario.png";
        //private static readonly string IMG__ENDING__SCENARIO_SUB_PNG = "img\\ending\\scenario_sub.png";
        //private static readonly string IMG__ENDING__SOUND_PNG = "img\\ending\\sound.png";
        //private static readonly string IMG__ENDING__SPRITE_SDF = "img\\ending\\sprite.sdf";
        //private static readonly string IMG__ENDING__SUB_SCENARIO_PNG = "img\\ending\\sub_scenario.png";
        //private static readonly string IMG__ENDING__SUOU_PNG = "img\\ending\\suou.png";
        //private static readonly string IMG__ENDING__TATUWO_PNG = "img\\ending\\tatuwo.png";
        //private static readonly string IMG__ENDING__VOICE_PNG = "img\\ending\\voice.png";
        //private static readonly string IMG__ENDING__YUHI_PNG = "img\\ending\\yuhi.png";

        #endregion

        #region メンバフィールド

        private GameSystem m_gSys;
        private Rand rand;
        private Sound bgm;
        private bool init = false;
        private bool initAfter = false;

        private bool headline;
        private bool drop;

        private int screenX;
        private int screenY;

        private readonly List<int> rolex = new List<int>();
        private readonly List<int> roley = new List<int>();
        private bool countAlpha;

        private RootCounterS roleAlpha;
        private RootCounterS ripplingTextureAlpha;

        private RipplingTexture ripplingTexture;		// 波紋描画テクスチャークラス
        private Surface[] surfaces;

        private ITexture bg;
        private ITexture role1;
        private ITexture role2;
        private readonly List<ITexture> drawRole = new List<ITexture>();

        private ITexture name1;
        private ITexture name2;
        private readonly List<ITexture> drawName = new List<ITexture>();

        private ReduceHeadlinear headlinear1;
        private ReduceHeadlinear headlinear2;

        private ScatteredTexture breakDrop1;
        private ScatteredTexture breakDrop2;
        private ScatteredTexture breakBg;
        private bool initDrop;

        private TextureLineNoise textureLineNoise1;
        private TextureLineNoise textureLineNoise2;

        private int step;

        private bool twoObject;

        private DropObjectManager snowDropMgr;	// 雪

        // 未使用
        //private MoveViewSmooth moveView;

        // 追加分
        private bool intro = true;	// イントロ部分
        private bool text;			// テキスト部分
        private bool textDrawEnd = true;
        private bool staff;			// スタッフ部分
        private bool endStep;		// 終了部分
        private bool initTimer;
        private ITexture caption;
        private ITexture heading;
        private ITexture endTelop;	// エンドテロップ
        private bool bEndTelop;

        private int mx;		// マウスの位置を保存しておく
        private int my;
        private int mstop;
        private bool mshow;
        private IMouseInput mouse;

        private List<SwallowDraw> sds;	// 吸い込まれテキストテクスチャ配列
        private List<string> message;	// ↑で使う、メッセージ配列
        private FixTimer timer;		// タイミング調整タイマ

        private ShellEmulatorDraw sed;

        private int counter = 0;
        private int add = int.MinValue;
        private int wait = 0;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="gameSystem"></param>
        public TrialEnding(GameSystem gameSystem)
        {
            m_gSys = gameSystem;
            // bgm
            bgm = new Sound();
            bgm.Load("snd/song/(I'll_Take_Myself)To_The_End.ogg", -1);

            ripplingTexture = new RipplingTexture();
            roleAlpha = new RootCounterS();
            breakDrop1 = new ScatteredTexture();
            breakDrop2 = new ScatteredTexture();
            breakBg = new ScatteredTexture();
            headlinear1 = new ReduceHeadlinear();
            headlinear2 = new ReduceHeadlinear();
            textureLineNoise1 = new TextureLineNoise();
            textureLineNoise2 = new TextureLineNoise();
            snowDropMgr = new DropObjectManager();
            rand = new Rand();
            rand.Randomize();
        }

        #region IDisposable メンバ

        public void Dispose()
        {
        }

        #endregion

        /// <summary>
        /// タスク処理
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public override int Task(object o)
        {
            GameSystem gameSystem = (GameSystem)o;
            if (0 == OnMove(gameSystem))
            {
                return 0;
            }
            gameSystem.OnMoveCommon();
            if (!gameSystem.FpsTimer.ToBeSkip)
            {
                gameSystem.Screen.Select();
                OnPaint(gameSystem);
                gameSystem.OnDrawCommon();
                gameSystem.Screen.Update();
            }
            else
            {
                OnPaint(gameSystem);
                gameSystem.OnDrawCommon();
            }
            return 1;
        }

        private int OnMove(GameSystem gameSystem)
        {
            if (!init)
            {
                init = true;
                onInit();
                m_gSys.Screen.SetClearColor(0, 0, 0);
                this.mouse = m_gSys.Mouse;
                this.mouse.GetPos(out mx, out my);
                this.mshow = true;
                // onInitでロードスレッドが起動する
                return 0;
            }

            if (CAP_SCREEN)
            {
                // タイマー調整
                if (null != timer)
                {
                    timer.Time = (int)(startTime + (taskLoopCount * (1000 / 60.0f)));
                    timer.Update();
                }
            }

            if (!initAfter)
            {
                // BGM再生開始
                //bgm.Play();
                // タイマ生成
                timer = new FixTimer();
                timer.Reset();
                initAfter = true;
            }

            int x, y;
            this.mouse.GetPos(out x, out  y);

            // 必要なければマウスカーソルを非表示する
            if (mx != x || my != y)
            {
                if (!mshow)
                {
                    mouse.Show();
                    mshow = true;
                }
                mstop = 0;
            }
            else
            {
                if (mshow)
                {
                    ++mstop;
                    if (mstop >= 30)
                    {
                        mouse.Hide();
                        mstop = 0;
                        mshow = false;
                    }
                }
            }

            this.mx = x;
            this.my = y;

            if (staff && step < STAFF_STEP_MAX)
            {
                ripplingTexture.OnMove(m_gSys.Screen);
                headline = headlinear1.IsFinish;
                if (twoObject)
                {
                    headline = headlinear2.IsFinish;
                }
                drop = breakDrop1.IsFinish();
                if (twoObject)
                {
                    drop = (bool)(drop && breakDrop2.IsFinish());
                }

                if (!headline || countAlpha)
                {
                    roleAlpha++;
                }

                ripplingTextureAlpha++;
                if (ripplingTextureAlpha.IsEnd && ripplingTextureAlpha.Value() == 0)
                {
                    ripplingTexture.SetSurface(surfaces[step]);
                    ripplingTextureAlpha.Set(0, Y4dConst.C_ALPHA_MAX, 2);
                }

                if (headline && !drop)
                {
                    if (!initDrop)
                    {
                        int x1, y1;
                        headlinear1.GetXY(out x1, out  y1);
                        breakDrop1.SetXY(x1, y1);
                        textureLineNoise1.SetXY(x1, y1);
                        breakDrop1.DivisionTexture(30, 10);	// 分割数
                        if (twoObject)
                        {
                            headlinear2.GetXY(out x1, out  y1);
                            breakDrop2.SetXY(x1, y1);
                            textureLineNoise2.SetXY(x1, y1);
                            breakDrop2.DivisionTexture(30, 10);	// 分割数
                        }
                        initDrop = true;
                    }

                    breakDrop1.OnMove(m_gSys.Screen);
                    checkBreakObj(breakDrop1);
                    if (twoObject)
                    {
                        breakDrop2.OnMove(m_gSys.Screen);
                        checkBreakObj(breakDrop2);
                    }

                    if (breakDrop1.IsBreaking() && !countAlpha)
                    {
                        countAlpha = true;
                        roleAlpha.Set(Y4dConst.C_ALPHA_MAX, 0, ROLE_ALPHA_STEP);
                        ripplingTextureAlpha.Set(Y4dConst.C_ALPHA_MAX, 0, -1);
                    }
                }
                else
                {
                    countAlpha = false;
                }

                breakBg.OnMove(m_gSys.Screen);

                if (headline && drop)
                {
                    // 次のロールへ
                    step++;

                    //Log.print("Now Step:%s\n", step);
                }

                //  次のステップへ
                if (headline && drop && step <= 13)
                {

                    drawRole.Clear();
                    drawName.Clear();
                    rolex.Clear();
                    roley.Clear();

                    switch (step)
                    {
                        case 1:		// シナリオ/シナリオ演出・構成
                            role1.Dispose();
                            //role2.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/scenario.png");
                            role2 = YamalibConst.CreateTexture("img/ending/scenario_sub.png");
                            //role1.load("img/ending/scenario.png");		// シナリオ
                            //role2.load("img/ending/scenario_sub.png");	// シナリオ演出・構成
                            drawRole.Add(role1);
                            drawRole.Add(role2);

                            // 表示位置の指定
                            rolex.Add(rolePos[(int)ROLE_POS.SCENARIO][0]);
                            roley.Add(rolePos[(int)ROLE_POS.SCENARIO][1]);
                            rolex.Add(rolePos[(int)ROLE_POS.SCENARIO_EDIT][0]);
                            roley.Add(rolePos[(int)ROLE_POS.SCENARIO_EDIT][1]);

                            name1.Dispose();
                            //name2.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/alice.png");
                            name2 = YamalibConst.CreateTexture("img/ending/g9fried.png");
                            //name1.load("img/ending/alice.png");
                            //name2.load("img/ending/g9fried.png");
                            drawName.Add(name1);
                            drawName.Add(name2);
                            textureLineNoise1.Texture = (name1);
                            textureLineNoise2.Texture = (name2);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            headlinear1.SetXY(namePos[(int)NAME_POS.SCENARIO][0], namePos[(int)NAME_POS.SCENARIO][1]);
                            //headlinear1.setSprite(sl.getSprite(), Name.ALICE);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            headlinear1.Reverse = (false);
                            AddTexture(headlinear1, "img/ending/alice/img.lst");


                            headlinear2.Clear();	// 初期化
                            headlinear2.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            headlinear2.SetXY(namePos[(int)NAME_POS.SCENARIO_EDIT][0], namePos[(int)NAME_POS.SCENARIO_EDIT][1]);
                            //headlinear2.setSprite(sl.getSprite(), Name.G9);
                            headlinear2.SetMargin(0, 15, 0, 20);
                            headlinear2.Interval = (HEADLINE_INTERVAL);
                            headlinear2.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear2.SetStartRate(HEADLINE_RATE);
                            headlinear2.Reverse = (true);
                            AddTexture(headlinear2, "img/ending/g9/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            breakDrop2.Clear();
                            breakDrop2.SetTexture(name2);
                            breakDrop2.SetFade(true, 4);
                            breakDrop2.SetWaitCount(BREAK_WAIT);

                            twoObject = true;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);

                            break;

                        case 2:	// プログラム
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/program.png");
                            //role1.load("img/ending/program.png");		// プログラム
                            drawRole.Add(role1);

                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/kowasuhito.png");
                            //name1.load("img/ending/kowasuhito.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);
                            setRoleCentering(role1, int.MinValue);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.KOW);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/kowasuhito/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);

                            twoObject = false;
                            break;

                        case 3:	// ２Ｄグラフィック
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/gra.png");
                            //role1.load("img/ending/gra.png"); 		// グラフィック
                            drawRole.Add(role1);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/nichino.png");
                            //name1.load("img/ending/nichino.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);
                            setRoleCentering(role1, int.MinValue);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.NICHI);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/nitino/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            twoObject = false;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            break;

                        case 4:	// 音楽・効果音・音声編集
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/sound.png");
                            //role1.load("img/ending/sound.png");
                            drawRole.Add(role1);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/g9fried.png");
                            //name1.load("img/ending/g9fried.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);
                            setRoleCentering(role1, int.MinValue);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.G9);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/g9/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            twoObject = false;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            break;

                        case 5:	// インターフェースデザイン
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/interface.png");
                            //role1.load("img/ending/interface.png");		// インターフェースデザイン
                            drawRole.Add(role1);

                            // 表示位置の指定
                            rolex.Add(rolePos[(int)ROLE_POS.INTERFACE][0]);
                            roley.Add(rolePos[(int)ROLE_POS.INTERFACE][1]);

                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/hara.png");
                            //name1.load("img/ending/hara.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);
                            setRoleCentering(role1, int.MinValue);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.HARA);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/hara/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            twoObject = false;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            break;

                        case 6:
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/sub_scenario.png");
                            //role1.load("img/ending/sub_scenario.png");	// サブシナリオ
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);

                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/g9fried.png");
                            //name1.load("img/ending/g9fried.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            // 表示位置の指定
                            rolex.Add(rolePos[(int)ROLE_POS.INTERFACE][0]);
                            roley.Add(rolePos[(int)ROLE_POS.INTERFACE][1]);
                            rolex.Add(rolePos[(int)ROLE_POS.PLAN][0]);
                            roley.Add(rolePos[(int)ROLE_POS.PLAN][1]);
                            rolex.Add(rolePos[(int)ROLE_POS.CREATE][0]);
                            roley.Add(rolePos[(int)ROLE_POS.CREATE][1]);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.G9);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/g9/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            twoObject = false;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            break;

                        case 7:
                            // ロールの読み込み
                            role1.Dispose();
                            role1 = YamalibConst.CreateTexture("img/ending/voice.png");
                            //role1.load("img/ending/voice.png");	// 声優
                            drawRole.Add(role1);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/amua.png");
                            //name1.load("img/ending/amua.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);
                            setRoleCentering(role1, int.MinValue);

                            // ありす
                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.AMUA);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/amua/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            twoObject = false;
                            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            break;

                        case 8:
                            // 翠子
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/suou.png");
                            //name1.load("img/ending/suou.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.SUOU);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/suou/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(Y4dConst.C_ALPHA_MAX, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            twoObject = false;
                            break;

                        case 9:
                            // タツヲ
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/tatuwo.png");
                            //name1.load("img/ending/tatuwo.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.TATUWO);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/tatuwo/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(Y4dConst.C_ALPHA_MAX, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            twoObject = false;
                            break;

                        case 10:
                            // 富絵
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/hazuki.png");
                            //name1.load("img/ending/hazuki.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.HAZUKI);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/hazuki/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(Y4dConst.C_ALPHA_MAX, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            twoObject = false;
                            break;

                        case 11:
                            // 安西
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/anzai.png");
                            //name1.load("img/ending/anzai.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.ANZAI);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/anzai/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(Y4dConst.C_ALPHA_MAX, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            twoObject = false;

                            // そろそろ雪を止ませる
                            //Log.printLook("STOP snow");
                            snowDropMgr.Stop(10000);

                            break;

                        case 12:
                            // ルビ
                            drawRole.Add(role1);
                            setRoleCentering(role1, int.MinValue);
                            name1.Dispose();
                            name1 = YamalibConst.CreateTexture("img/ending/haruhi.png");
                            //name1.load("img/ending/haruhi.png");
                            drawName.Add(name1);
                            textureLineNoise1.Texture = (name1);

                            headlinear1.Clear();	// 初期化
                            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
                            //headlinear1.setSprite(sl.getSprite(), Name.HARUHI);
                            headlinear1.SetMargin(0, 15, 0, 20);
                            headlinear1.Interval = (HEADLINE_INTERVAL);
                            headlinear1.SetStartRate(HEADLINE_RATE);
                            AddTexture(headlinear1, "img/ending/haruhi/img.lst");

                            // BreadDrop の設定
                            breakDrop1.Clear();
                            breakDrop1.SetTexture(name1);
                            breakDrop1.SetFade(true, 4);
                            breakDrop1.SetWaitCount(BREAK_WAIT);

                            roleAlpha.Set(Y4dConst.C_ALPHA_MAX, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);
                            twoObject = false;
                            break;

                        default:
                            //Log.printError("invalied step:%s\n",step);
                            break;
                    }

                    headline = drop = initDrop = false;
                }
            }
            else if (staff)
            {
                ripplingTexture.OnMove(m_gSys.Screen);
                ripplingTextureAlpha++;
                // スタッフフェーズの終了判定	
                if (step == STAFF_STEP_MAX && ripplingTextureAlpha.IsEnd)
                {
                    staff = false;
                }
            }
            timer.Update();

            if (!staff && !text && timer.Time < START_END_MS)
            {
                if (timer.Time >= START_TXT_MS)
                {
                    text = true;
                    textDrawEnd = false;
                    intro = false;
                }
            }
            else if (text)
            {
                if (timer.Time >= START_END_MS)
                {
                    text = false;
                    //				endStep = true;
                }
            }

            if (!endStep && timer.Time >= START_COMMAND_MS)
            {
                //Log.printLook("END STEP START!!");
                endStep = true;
            }

            if (!bEndTelop && timer.Time >= START_END_TELOP_MS)
            {
                bEndTelop = true;
                ripplingTextureAlpha.Set(0, 255, 1);
            }

            if (endStep)
            {
                sed.OnMove(m_gSys.Screen);
            }

            if (bEndTelop)
            {
                ripplingTextureAlpha++;

                if (timer.Time >= START_END_TASK_MS && ripplingTextureAlpha.Value() == 255)
                {
                    // 画面をフェードアウトしてから遷移しようっと
                    ripplingTextureAlpha.Set(255, 0, 1);
                }

                if (ripplingTextureAlpha.Value() == 0)
                {
                    // タイトルへ遷移
                    m_gSys.SceneController.JumpScene(Scenes.Startmenu);
                    if (!mshow)
                    {
                        this.mouse.Show();
                    }
                    return 1;
                }
            }

            if (text || !textDrawEnd)
            {
                textMove();
            }

            if (!initTimer)
            {
                initTimer = true;
                //Log.printLook("ENDING TIMER REST!");
                timer.Reset();
            }
            return 1;
        }

        private void OnPaint(GameSystem gameSystem)
        {
            m_gSys.Screen.Clear();

            // エンドステップフェーズ
            if (endStep)
            {
                sed.OnDraw(m_gSys.Screen);
            }

            // イントロフェーズ
            if (intro)
            {
                introDraw();
            }

            // スタッフフェーズ
            if (staff)
            {
                m_gSys.Screen.SetColor(255, 255, 255, ripplingTextureAlpha.Value());
                onDrawRipplingTexture();

                if (step != STAFF_STEP_MAX)
                {
                    m_gSys.Screen.SetColor(255, 255, 255, roleAlpha.Value());
                    // ロールの描画
                    for (int i = 0; i < drawRole.Count; i++)
                    {
                        m_gSys.Screen.Blt(drawRole[i], rolex[i], roley[i]);
                    }

                    m_gSys.Screen.ResetColor();

                    if (!headline)
                    {
                        // 名前のエフェクト描画
                        headlinear1.OnDraw(m_gSys.Screen);
                        if (twoObject)
                            headlinear2.OnDraw(m_gSys.Screen);
                    }
                    else if (headline && !drop)
                    {
                        if (breakDrop1.IsWait())
                        {
                            textureLineNoise1.OnPaint(m_gSys.Screen);
                            if (twoObject)
                                textureLineNoise2.OnPaint(m_gSys.Screen);
                        }
                        else
                        {
                            breakDrop1.OnDraw(m_gSys.Screen);
                            if (twoObject)
                                breakDrop2.OnDraw(m_gSys.Screen);
                        }
                    }
                }

                // 雪でも降らせてみる？
                snowDropMgr.OnDraw(m_gSys.Screen);
                createWaveWithSnow();

                m_gSys.Screen.SetColor(255, 255, 255, 96);
                // キャプション 
                m_gSys.Screen.Blt(caption, 350, 10);

            }

            // テキストフェーズ
            if (text || !textDrawEnd)
            {
                textDraw();
            }

            if (bEndTelop)
            {
                m_gSys.Screen.SetColor(255, 255, 255, ripplingTextureAlpha.Value());
                m_gSys.Screen.Blt(endTelop, 0, 0);
            }

            if (CAP_SCREEN)
            {
                if (0 == taskLoopCount % 2)
                {
                    StoreScreenShot();
                }
                taskLoopCount++;
            }
        }

        #region 非公開メンバ

        private static readonly Point[] points = new Point[]{
			    new Point(150, 230),
			    new Point(490, 230),
			    new Point(640, 480),
			    new Point(0, 480),
            };
        /// 背景波紋テクスチャの描画
        private void onDrawRipplingTexture()
        {
            m_gSys.Screen.Blt(ripplingTexture.GetTexture(), (Rect)null, points);
        }

        /// 初期化処理を行う
        private void onInit()
        {
            // アルファ可能にしとく
            m_gSys.Screen.BlendSrcAlpha();
            // 速度調整		
            //FSP_RATE = KyojinConst.C_FSP_DEFAULT / KyojinConst.C_FSP_NOW;

            // BGMのボリュームはオプション画面のボリュームにしとっかー
            bgm.Volume = m_gSys.OptionInfo.BGMVolume / 100.0f;

            onLoad();
            //auto dg = &onLoad;
            //m_gSys.gameSceneController.callScene(KyojinConst.Task.Task_Loader, dg);
            //Log.printLook("Loader Thread setting..");

        }

        private void AddTexture(ReduceHeadlinear headlinear, string defFilename)
        {
            TextureLoader tl = m_gSys.SmartTextureLoader.LoadDefFile(defFilename, true);
            int elementNum = YanesdkUtil.GetElementNum(defFilename);
            for (int i = 0; i < elementNum; i++)
            {
                headlinear.AddTexture(tl.GetTexture(i));
            }
        }

        private int onLoad()
        {
            screenX = m_gSys.Screen.Width;
            screenY = m_gSys.Screen.Height;

            //// moveview
            //moveView = new MoveViewSmooth();
            //moveView.setTextureLoader(m_gSys.tl_bg);
            //moveView.setMoveXY(0.5f, 0.2f);

            //sl.load(getFullName(IMG__ENDING__SPRITE_SDF));
            name1 = YamalibConst.CreateTexture(IMG__ENDING__KOWASUHITO_PNG);
            //name1.load(getFullName(IMG__ENDING__KOWASUHITO_PNG));

            role1 = YamalibConst.CreateTexture(IMG__ENDING__COMMAND_PNG);
            //role1.load(getFullName(IMG__ENDING__COMMAND_PNG));	// 製作総指揮
            setRoleCentering(role1, int.MinValue);

            textureLineNoise1.Texture = (name1);
            textureLineNoise1.Interval = (50);

            bg = YamalibConst.CreateTexture(IMG__ENDING__BG_JPG);
            //bg.load(getFullName(IMG__ENDING__BG_JPG));

            //headlinear用TextureLoader 準備
            headlinear1.Clear();
            headlinear1.SetStyle((int)ReduceHeadlinear.Style.CENTER);
            headlinear1.SetMargin(0, 15, 0, 20);
            headlinear1.Interval = (HEADLINE_INTERVAL);
            headlinear1.SetEffectingFrame(HEADLINE_EFFECT_TIME);
            headlinear1.SetMoveXY(-300, -200);
            headlinear1.Reverse = (true);
            AddTexture(headlinear1, "img/ending/kowasuhito/img.lst");


            //		headlinear1.SetRandomMove(true);

            // BreadDrop の設定
            breakDrop1.SetTexture(name1);
            breakDrop1.SetWaitCount(BREAK_WAIT);
            breakDrop1.SetFade(true, 4);
            roleAlpha.Set(0, Y4dConst.C_ALPHA_MAX, ROLE_ALPHA_STEP);

            //Surface surface = new Surface();
            //surface.Load((IMG__ENDING__MASK1_PNG));
            //t = YamalibConst.CreateTexture(IMG__BACK__PLACE010_JPG);
            ////t.load(IMG__BACK__PLACE010_JPG);
            //breakBg.SetTexture(t);
            //breakBg.SetWaitCount(BREAK_WAIT);
            //breakBg.SetFade(true, 4);
            //breakBg.DivisionTextureWithSurface(surface, 2, 2);

            drawRole.Add(role1);
            drawName.Add(name1);

            // 雪
            snowDropMgr = new DropObjectManager();
            snowDropMgr.PresetSnow();
            snowDropMgr.Init(250);

            // -------------------------追加分
            caption = YamalibConst.CreateTexture("img/ending/caption.png");
            heading = YamalibConst.CreateTexture("img/ending/heading.jpg");

            surfaces = new Surface[13];
            for (int i = 0; i < surfaces.Length; i++)
            {
                surfaces[i] = new Surface();
                surfaces[i].Load(SURFACE_NAME[i]);
            }

            ripplingTexture.SetSurface(surfaces[0]);
            ripplingTextureAlpha = new RootCounterS();
            ripplingTextureAlpha.Set(0, Y4dConst.C_ALPHA_MAX, -1);

            // テキスト読み込み
            //std.stream.MemoryStream m =
            //    new std.stream.MemoryStream(FileSys.read("data/ending.txt"));
            //while (!m.eof)
            //{
            //    string linebuf = m.readLine();
            //    message.Add(linebuf);
            //}
            message = LoadMessage("data/ending.txt", int.MaxValue);

            // 吸い込みテクスト生成
            sds = new List<SwallowDraw>(9);
            int drawWait = 0;
            for (int i = 0; i < sds.Capacity; i++)
            {
                SwallowDraw sd = new SwallowDraw();
                drawWait += 18;
                ITexture tmp = YamalibConst.CreateTexture();
                string str = message[rand.GetRand(message.Count)];
                if (str.Length >= 10)
                {
                    str = str.Substring(0, 9);
                }
                tmp.SetSurface(m_gSys.CommonFontLoader.GetFont(KyojinConst.SCENARIO_KYOJIN_TEXT_FONT_NO).DrawBlendedUnicode(str));
                sd.SetTexture(tmp);
                sd.SetDrawWait(drawWait);
                sd.SetEndStep(90);
                sds.Add(sd);
            }

            // シェルエミュレートドロー生成
            string[] COMMAND_FILE = new string[]{
                        "img/ending/sh/sh1.txt",
                        "img/ending/sh/sh2.txt",
                        "img/ending/sh/sh3.txt",
                        "img/ending/sh/sh4.txt",
                    };

            sed = new ShellEmulatorDraw();
            sed.SetCommands(COMMAND_FILE, m_gSys.CommonFontLoader);

            // エンドテクスチャ生成
            endTelop = YamalibConst.CreateTexture("img/ending/endtelop.jpg");

            return 0;
        }

        private List<string> LoadMessage(string filename, int maxLength)
        {
            List<string> result = new List<string>();
            string strText = Yamalib.Util.YamalibUtility.ReadTextFile(filename);
            string[] strLine = strText.Split(new char[] { '\n' });
            foreach (string str in strLine)
            {
                if (str == null || str.Length == 0)
                {
                    continue;
                }
                if (str.Length > maxLength)
                {
                    result.Add(str.Substring(0, maxLength));
                }
                else
                {
                    result.Add(str);
                }
            }

            return result;
        }


        /// 役割画像をセンタリングする
        private void setRoleCentering(ITexture t, int y/*=int.min*/)
        {
            rolex.Add((screenX - (int)t.Width) / 2);
            if (y == int.MinValue)
            {
                roley.Add(ROLE_Y);
            }
            else
            {
                roley.Add(y);
            }
        }

        private void createWaveWithSnow()
        {
            foreach (DropObject dropOjb in snowDropMgr.GetPool())
            {
                if (dropOjb.IsAlive)
                {
                    float x, y;
                    dropOjb.GetXY(out x, out y);
                    if (y > 240 + ((dropOjb.GetDepth() - 0.5f) * 250.0f))
                    {
                        ripplingTexture.CreateWave((int)(x * ((float)240 / 640)), (int)y - 250, -64 * 256);
                        dropOjb.Kill();
                    }
                }
            }
        }

        /// 分解した文字が水面に接地したときに波紋を起こす
        private void checkBreakObj(ScatteredTexture st)
        {
            if (!st.IsBreaking()) return;

            foreach (ScatteredTexture.BreakObject bo in st.GetObjectInfo())
            {
                if (bo.posy > 430)
                {
                    ripplingTexture.CreateWave((int)((float)bo.posx * ((float)240 / 640)), 200 + (rand.GetRand(20) - 10), -250 * 256);
                    bo.Kill();
                }
            }
        }

        /// テキスト描画移動
        private void textMove()
        {
            bool textEnd = true;

            if (!text)
            {

                foreach (SwallowDraw sd in sds)
                {
                    sd.OnMove(m_gSys.Screen);
                    if (!sd.IsEnd())
                    {
                        textEnd = false;
                    }
                }

                if (textEnd)
                {
                    textDrawEnd = true;
                }

            }
            else
            {

                foreach (SwallowDraw sd in sds)
                {
                    sd.OnMove(m_gSys.Screen);
                    if (sd.IsEnd())
                    {
                        ITexture tmp = YamalibConst.CreateTexture();

                        string str = (message[rand.GetRand(message.Count)]);
                        tmp.SetSurface(
                            m_gSys.CommonFontLoader.GetFont(KyojinConst.SCENARIO_KYOJIN_TEXT_FONT_NO).DrawBlendedUnicode(str));

                        sd.SetTexture(tmp);
                        sd.Reset();
                    }
                }

            }

        }

        /// テキスト描画
        private void textDraw()
        {
            foreach (SwallowDraw sd in sds)
            {
                sd.OnDraw(m_gSys.Screen);
            }
        }

        /// イントロ部分
        void introMove()
        {
        }

        /// イントロ部分描画
        private void introDraw()
        {

            if (add == int.MinValue)
            {
                add = FSP_RATE * 1;
            }

            m_gSys.Screen.SetColor(255, 255, 255, (counter += add));

            if (counter >= 255)
            {
                if (wait++ > (100 / FSP_RATE))
                {
                    add = (-1 * FSP_RATE);
                }
                else
                {
                    add = 0;
                }
            }
            else if (counter <= 0)
            {
                add = 0;
            }

            // 表題描画
            m_gSys.Screen.Blt(heading, 0, 0);

            if (add < 0 && counter <= 96)
            {
                m_gSys.Screen.SetColor(255, 255, 255, 96);
            }

            if (counter <= 0)
            {
                intro = false;
                staff = true;
            }

            // キャプション
            m_gSys.Screen.Blt(caption, 350, 10);
        }

        #endregion


        #region スクリーンキャプチャ用メソッド

        private IntPtr hwnd = IntPtr.Zero;

        private long taskLoopCount = 0;
        private int startTime = 0;
        private long fileNo = 0;
        private System.Drawing.Rectangle windowRect = new System.Drawing.Rectangle(new System.Drawing.Point(5, 5), new System.Drawing.Size(648, 488));
        private string basePath = "d:\\img_trialending\\";

        private void StoreScreenShot()
        {
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
              windowRect.Width, windowRect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
            {
                g.CopyFromScreen(windowRect.X, windowRect.Y, 0, 0,
                  windowRect.Size, System.Drawing.CopyPixelOperation.SourceCopy);
            }

            long dirNum = (fileNo / 500);
            if (fileNo % 500 == 0)
            {
                System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(basePath + dirNum.ToString());
                dirInfo.Create();
            }

            string filePath = basePath + dirNum.ToString() + "\\" + fileNo.ToString("d8") + ".bmp";

            bmp.Save(filePath, System.Drawing.Imaging.ImageFormat.Bmp);
            fileNo++;
        }





        #endregion

    }
}
