using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.Timer;
using Yanesdk.Draw;
using Yamalib.Util;
using Yamalib.Yanesdkext.Draw;

namespace Kyojin.Component.Ending
{
    public class Scene02 : EndingSceneBase, IDisposable
    {

        /** 描画クラス */
        protected class PhaseDraw
        {
            /// 初期化処理
            public PhaseDraw(TextureLoader loader, int bgNo)
            {
                //Debug (loader !is null);
                txtureLoader = loader;
                this.bgNo = bgNo;
                alpha = new RootCounterS(255, 255, 1);
            }

            ///　終了フラグ
            public bool IsEnd()
            {
                return end;
            }
            public bool IsEnd(bool value)
            {
                return end = value;
            }

            // 開始フラグ
            public bool IsStart()
            {
                return start;
            }
            public bool IsStart(bool value)
            {
                return start = value;
            }

            // フェードスタート
            public void FadeStart()
            {
                start = true;
                alpha.Set(0, 255, 7);
            }

            // フェードスタート
            public void FadeEnd()
            {
                alpha.Set(255, 0, 7);
                fadeEndFlg = true;
            }

            /// 動作処理
            public void OnMove(IScreen screen)
            {
                if (!end)
                {
                    alpha.Inc();
                    if (fadeEndFlg && alpha.IsEnd)
                    {
                        end = true;
                        //Log.print("PHASE EDN\n");
                    }
                    foreach (Phase1Base p in phase)
                    {
                        p.OnMove(screen);
                    }
                }
            }

            /// 描画処理
            public void OnDraw(IScreen screen)
            {
                if (start && !end)
                {
                    // 背景描画
                    screen.SetColor(255, 255, 255, alpha.Value());
                    screen.Blt(txtureLoader.GetTexture(bgNo), 0, 0);
                    foreach (Phase1Base p in phase)
                    {
                        p.OnDraw(screen);
                    }
                }
            }

            /// 次の画像を追加
            public void Next(TextObj obj, HitStatus status, int imgNo, int x, int y, int effectNo)
            {
                Phase1Base instance = new Phase1Base(obj, txtureLoader, status);
                instance.SetImgNo(imgNo);
                instance.SetXY(x, y);
                instance.GetTransCounter().Set(0, 255, 7);
                instance.SetEffectNo(effectNo);

                phase.Add(instance);
            }


            private RootCounterS alpha;
            private bool fadeEndFlg;
            private bool start;
            private bool end;
            private TextureLoader txtureLoader;
            private int bgNo;
            private readonly List<Phase1Base> phase = new List<Phase1Base>();
        }

        #region 定数値

        protected const int P1_1_FADEOUT_SPEED = 10;
        protected const int LOGO_X = 320;
        protected const int LOGO_Y = 120;
        // 念のため時間でも終了時間もチェック
        private const long END_TIME = 89300 + MUSIC_OFFSET_TIME;
        private const long START_TIME = 65000 + MUSIC_OFFSET_TIME;

        #endregion

        #region メンバフィールド

        protected readonly List<PhaseBase> activePhase = new List<PhaseBase>();
        protected TextureLoader textureLoader;
        protected FixTimer timer;
        protected bool sceneEndFlg = false;
        protected bool startFlg = false;
        protected readonly List<HittingEffect> hitEffects = new List<HittingEffect>();

        private PhaseDraw phase1_1;
        private PhaseDraw phase1_2;
        private PhaseDraw phase2_1;
        private PhaseDraw phase2_2;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="timer"></param>
        public Scene02(FixTimer timer)
        {
            textureLoader = new TextureLoader();
            textureLoader.IsDefRelativePath = false;
            textureLoader.LoadDefFile("img2/ending/s02/list.txt");
            this.timer = timer;
            SetupTimingData();
        }

        /// すべての画像をキャッシュする	
        public override void CacheTexture()
        {
            CacheTextureAll(textureLoader, "img2/ending/s02/list.txt");
        }

        // シーンは開始しているか
        public override bool IisStart
        {
            get { return START_TIME <= timer.Time; }
        }

        // シーンが終了したか
        public override bool IsEnd
        {
            get { return sceneEndFlg || END_TIME <= timer.Time; }
        }

        // リソースの解放
        public override void Release()
        {
            textureLoader.Dispose();
        }

        /// タイミングデータ作成
        protected virtual void SetupTimingData()
        {
            TimingData[] t2_1 = {
			    new TimingData(MUSIC_OFFSET_TIME + 65480,  new HitEvent[]{eventCallback1_1}),
			    new TimingData(MUSIC_OFFSET_TIME + 66820,  new HitEvent[]{eventCallback1_2}),
			    new TimingData(MUSIC_OFFSET_TIME + 68160,  new HitEvent[]{eventCallback1_3}),
			    new TimingData(MUSIC_OFFSET_TIME + 69490,  new HitEvent[]{eventCallback1_4}),
			    new TimingData(MUSIC_OFFSET_TIME + 69650,  new HitEvent[]{eventCallback1_5}),
			    new TimingData(MUSIC_OFFSET_TIME + 70830,  new HitEvent[]{eventCallback1_6}),
			    new TimingData(MUSIC_OFFSET_TIME + 72160,  new HitEvent[]{eventCallback1_7}),
			    new TimingData(MUSIC_OFFSET_TIME + 73490,  new HitEvent[]{eventCallback1_8}),
			    new TimingData(MUSIC_OFFSET_TIME + 74160,  new HitEvent[]{eventCallback1_9}),
			    new TimingData(MUSIC_OFFSET_TIME + 74270,  new HitEvent[]{eventCallback1_10}),
			    new TimingData(MUSIC_OFFSET_TIME + 74650,  new HitEvent[]{eventCallback1_11}),
			    new TimingData(MUSIC_OFFSET_TIME + 74840,  new HitEvent[]{eventCallback1_12}),
			    new TimingData(MUSIC_OFFSET_TIME + 74950,  new HitEvent[]{eventCallback1_13}),
            };
            m_timingData.Add(t2_1);

            TimingData[] t2_2 = {
			    new TimingData(MUSIC_OFFSET_TIME + 76150,  new HitEvent[]{eventCallback2_1}),
			    new TimingData(MUSIC_OFFSET_TIME + 77490,  new HitEvent[]{eventCallback2_2}),
			    new TimingData(MUSIC_OFFSET_TIME + 78820,  new HitEvent[]{eventCallback2_3}),
			    new TimingData(MUSIC_OFFSET_TIME + 80190,  new HitEvent[]{eventCallback2_4}),
			    new TimingData(MUSIC_OFFSET_TIME + 80330,  new HitEvent[]{eventCallback2_5}),
			    new TimingData(MUSIC_OFFSET_TIME + 81610,  new HitEvent[]{eventCallback2_6}),
			    new TimingData(MUSIC_OFFSET_TIME + 82820,  new HitEvent[]{eventCallback2_7}),
			    new TimingData(MUSIC_OFFSET_TIME + 83490,  new HitEvent[]{eventCallback2_8}),
			    new TimingData(MUSIC_OFFSET_TIME + 84150,  new HitEvent[]{eventCallback2_9}),
			    new TimingData(MUSIC_OFFSET_TIME + 84800,  new HitEvent[]{eventCallback2_10}),
			    new TimingData(MUSIC_OFFSET_TIME + 85550,  new HitEvent[]{eventCallback2_11}),
			    new TimingData(MUSIC_OFFSET_TIME + 87480,  new HitEvent[]{eventCallback2_12}),
			    new TimingData(MUSIC_OFFSET_TIME + 87840,  new HitEvent[]{eventCallback2_13}),
			    new TimingData(MUSIC_OFFSET_TIME + 88000,  new HitEvent[]{eventCallback2_14}),
			    new TimingData(MUSIC_OFFSET_TIME + 88300,  new HitEvent[]{eventCallback2_15}),
            };
            m_timingData.Add(t2_2);

            phase1_1 = new PhaseDraw(textureLoader, 0);
            phase1_1.FadeStart();
            phase1_2 = new PhaseDraw(textureLoader, 6);
            phase2_1 = new PhaseDraw(textureLoader, 15);
            phase2_2 = new PhaseDraw(textureLoader, 21);
        }

        public override void OnMove(IScreen screen)
        {
            if (!startFlg)
            {
                if (START_TIME <= timer.Time)
                {
                    startFlg = true;
                }
            }
            else
            {
                phase1_1.OnMove(screen);
                phase1_2.OnMove(screen);
                phase2_1.OnMove(screen);
                phase2_2.OnMove(screen);
                foreach (HittingEffect hitEffect in hitEffects)
                {
                    if (hitEffect != null)
                    {
                        hitEffect.OnMove(screen);
                    }
                }
            }
        }

        public override void OnDraw(IScreen screen)
        {
            if (startFlg)
            {
                phase1_1.OnDraw(screen);
                phase1_2.OnDraw(screen);
                phase2_1.OnDraw(screen);
                phase2_2.OnDraw(screen);
                foreach (HittingEffect hitEffect in hitEffects)
                {
                    if (hitEffect != null)
                    {
                        hitEffect.OnPaint(screen);
                    }
                }
            }
        }


        #region IDisposable メンバ

        public void Dispose()
        {
            Release();
        }

        #endregion


        #region ヒットイベント

        // ========================================================================================== //
        // =================================     PHASE 1 - 1     ==================================== //
        // ========================================================================================== //

        /// 1-1
        private bool eventCallback1_1(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_1.Next(textObj, status, 1, 15, 47, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-2
        private bool eventCallback1_2(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_1.Next(textObj, status, 2, 15, 81, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }
        /// 1-3
        private bool eventCallback1_3(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_1.Next(textObj, status, 3, 15, 115, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-4
        private bool eventCallback1_4(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_1.Next(textObj, status, 4, 15, 149, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-5
        private bool eventCallback1_5(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_1.Next(textObj, status, 5, 15, 251, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-6 有瀬
        private bool eventCallback1_6(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {

            // 前のフェーズを終わらせておく
            phase1_1.FadeEnd();

            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.FadeStart();
                phase1_2.Next(textObj, status, 7, 9, 49, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-7
        private bool eventCallback1_7(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 8, 9, 83, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-8
        private bool eventCallback1_8(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 9, 9, 117, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-9
        private bool eventCallback1_9(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 10, 9, 185, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-10
        private bool eventCallback1_10(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 11, 9, 219, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-11
        private bool eventCallback1_11(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 12, 9, 253, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-12
        private bool eventCallback1_12(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 13, 9, 287, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 1-13
        private bool eventCallback1_13(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase1_2.Next(textObj, status, 14, 9, 321, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }


        // ========================================================================================== //
        // =================================     PHASE 2 - 2     ==================================== //
        // ========================================================================================== //
        /// 2-1 リサ
        private bool eventCallback2_1(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {

            hitEffects.Clear();

            // 前のフェーズを終わらせておく
            phase1_2.FadeEnd();

            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_1.FadeStart();
                phase2_1.Next(textObj, status, 16, 11, 132, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }
        /// 2-2 
        private bool eventCallback2_2(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_1.Next(textObj, status, 17, 11, 199, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-3 
        private bool eventCallback2_3(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_1.Next(textObj, status, 18, 11, 264, 20);

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }
        /// 2-4
        private bool eventCallback2_4(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_1.Next(textObj, status, 19, 11, 300, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }
        /// 2-5　
        private bool eventCallback2_5(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_1.Next(textObj, status, 20, 11, 368, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }


        /// 2-6 ノゾミ
        private bool eventCallback2_6(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {

            // 前のフェーズを終わらせておく
            phase2_1.FadeEnd();

            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.FadeStart();
                phase2_2.Next(textObj, status, 22, 6, 15, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-7
        private bool eventCallback2_7(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 23, 6, 49, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-8
        private bool eventCallback2_8(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 24, 6, 83, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-9
        private bool eventCallback2_9(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 25, 6, 117, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-10
        private bool eventCallback2_10(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 26, 6, 151, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-11
        private bool eventCallback2_11(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 27, 6, 185, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-12
        private bool eventCallback2_12(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 28, 6, 219, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-13
        private bool eventCallback2_13(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 29, 6, 253, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-14
        private bool eventCallback2_14(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 30, 6, 287, 20);
                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        /// 2-15
        private bool eventCallback2_15(IScreen screen, TextObj textObj, long hitTime,
            HitStatus status)
        {
            // ステータスカウント
            CountHitStatus(status);
            if (IsHitedStatus(status))
            {
                phase2_2.Next(textObj, status, 31, 6, 321, 20);

                // 前のフェーズを終わらせておく
                phase2_2.FadeEnd();

                hitEffects.Add(CreateHitEffect(textObj));
            }
            // 後は自前でやるのででええわー
            return true;
        }

        #endregion


    }
}
