using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.System;
using Kyojin.Model;
using Yanesdk.Draw;
using Yamalib;
using Yamalib.GUI;
using Yanesdk.GUIParts;
using Kyojin.Scene.YesNo;
using Yamalib.Util;

namespace Kyojin.Scene.Selector
{
    class SelectorScene : TaskBase, IDisposable
    {
        #region 定数値

        /// シーケンスオブジェクトの有効矩形の枠サイズ
        private const int F_SIZE = 2;
        private enum CLASS : int { ACTOR = 0, S01, S02, S03, S04, S05, S06, S07, K01, K02, K03 };

        /// シーセンス図のパーツの描画位置
        private static readonly Point[] OBJ_POS = {
		    new Point(0,  0),		// アウター
		    new Point(16, 26),		// シナリオ１
		    new Point(16, 67),		// シナリオ２
		    new Point(193,151),		// シナリオ３
		    new Point(287,180),		// シナリオ４
		    new Point(359,208),		// シナリオ５
		    new Point(202,114),		// シナリオ６
		    new Point(461,142),		// シナリオ７
		    new Point(17, 224),		// 去人１
		    new Point(113,260),		// 去人２
		    new Point(205,295),		// 去人３
	    };

        /// タイトル名ボタン描画位置
        private static readonly Point[] TITLE_POS = {
		    new Point(102,37),	// シナリオ１
		    new Point(172,76),	// シナリオ２
		    new Point(265,166),	// シナリオ３
		    new Point(337,196),	// シナリオ４
		    new Point(404,228),	// シナリオ５
		    new Point(404,127),	// シナリオ６
		    new Point(508,157),	// シナリオ７
		    new Point(84, 242),	// 去人１
		    new Point(178,272),	// 去人２
		    new Point(281,302)	// 去人３
	    };
        private const int BT_MAIN_MAX = 6;

        /// ターミネーション描画位置
        private static readonly Point[] TERMI = {
		    new Point(28, 396),			// アウター
		    new Point(135,134),
		    new Point(206,238),
		    new Point(303,273),
		    new Point(371,294),
		    new Point(445,273),
		    new Point(475,215),
		    new Point(542,208),
		    new Point(115,342),
		    new Point(210,367),
		    new Point(315,411),
        };

        /// アウターシーケンスの描画量
        private static readonly int[] ACTOR_MAX = new int[] {
		    100,	// シナリオ１
		    245, 	// シナリオ２
		    300		// メイン終了
	    };

        /// Ｓ０２シーケンスの描画量
        private static readonly int[] S02_MAX = new int[]{
		    47,	// 読める
		    200, 	// 終了
	    };

        /// 戻るボタン描画位置
        private const int BACK_BT_X = 539;
        private const int BACK_BT_Y = 425;

        /// シナリオタイトル描画位置	
        private const int TITLE_NAME_X = 0;
        private const int TITLE_NAME_Y = 416;

        /// 最終メッセージ描画位置	
        private const int LAST_MSG_X = 0;
        private const int LAST_MSG_Y = 356;

        #endregion

        #region メンバフィールド

        private readonly Dictionary<int, int> texStoryMap = new Dictionary<int, int>();
        private static Dictionary<int, int> eyeTypeMap = new Dictionary<int, int>();

        private GameSystem m_gSys;
        private bool init;
        private bool showDialog;
        private bool exitScene;
        private bool[] readableFlags;			//!< UserInfoより描画用に変換された描画フラグ配列
        private bool[] termiFlags;			//!< 終端描画フラグ
        //private GUIButton btBack;			//!< 「戻る」ボタン

        //private int[2] m_param;
        //private int flameIndex;
        private readonly Rect rcActor = new Rect();	//!< アウター用表示矩形
        private readonly Rect rc2nd = new Rect();		//!< シナリオ２用表示矩形

        // パーツ刷新 ----------
        private TextureLoader m_seqParts;
        private TextureLoader m_titleNames;
        private ITexture m_imgLastMsg;
        private bool m_gameEnd;
        private int m_selectedIndex;
        private ITexture m_imgBg;	//!< 背景画像
        private ITexture m_imgTerm;		//!< ターミネーション画像

        //private GUIButton[] m_titleButtons;
        private ControlContext ctrlContext = new ControlContext();
        private FocusableTextureGUIControl textureGuiCtrl = new FocusableTextureGUIControl();
        private List<TextureGUIControl.Control> m_titleButtons = new List<TextureGUIControl.Control>();

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="gameSystem"></param>
        public SelectorScene(GameSystem gameSystem)
        {
            m_gSys = gameSystem;
            int i = 0;
            //texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.NOT_DATA);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY01);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY02_0);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY03);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY04);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY05);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY06);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.STORY07);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.KYOJIN01);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.KYOJIN02);
            texStoryMap.Add(i++, (int)KyojinConst.ScenarioID.KYOJIN03);
        }


        #region IDisposable メンバ

        public void Dispose()
        {
            YamalibUtility.Dispose(m_imgBg);
            YamalibUtility.Dispose(m_imgTerm);

            ctrlContext = null;
            textureGuiCtrl = null;
            m_titleButtons = null;
        }

        #endregion

        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;
        }

        /// <summary>
        /// 動作処理
        /// </summary>
        /// <param name="gameSystem"></param>
        private int OnMove(GameSystem gameSystem)
        {
            if (!init)
            {
                OnInit();
                init = true;
            }

            m_gSys.KeyDecolateMouse.Update();
            m_gSys.Key.Update();

            if (m_gSys.IsShowYesNo)
            {
                return 1;
            }

            // フォーカス
            textureGuiCtrl.OnMoveFocus();

            if (showDialog && YesNoScene.CLICK.NO_CLICK != m_gSys.YesnoClickState)
            {
                //Log.print("TASK_SCENARIO CLICK!!");
                // 上書き承認
                if (YesNoScene.CLICK.YES == m_gSys.YesnoClickState)
                {
                    //m_gSys.setData(m_param);
                    //m_gSys.hideDialog();
                    // 一度描画させて、ダイアログを消してから遷移する
                    exitScene = true;
                    //Log.print("JUMP SCENARIO TASK");
                    return 1;
                }
                showDialog = false;
            }

            int i = 0;
            foreach (TextureGUIControl.Control control in m_titleButtons)
            {
                FocusableTextureButton bt = control.Parts as FocusableTextureButton;
                if (bt.IsHover)
                {
                    ButtonActive(i, false);
                }
                ++i;
            }
            return 1;
        }

        /// 対象のボタンをアクティブに、他を元に戻す
        private void ButtonActive(int index, bool force)
        {
            if (index < 0)
            {
                return;
            }

            if (m_selectedIndex != index || force)
            {
                // 今アクティブになっているものを元に戻す
                {
                    FocusableTextureButton bt = m_titleButtons[m_selectedIndex].Parts as FocusableTextureButton;
                    bt.LoaderOffset -= 1;
                }
                // 今アクティブのものをONにする
                {
                    FocusableTextureButton bt = m_titleButtons[index].Parts as FocusableTextureButton;
                    bt.LoaderOffset += 1;
                }
                m_selectedIndex = index;
            }
        }

        /// <summary>
        /// 描画処理
        /// </summary>
        /// <param name="gameSystem"></param>
        private void OnPaint(GameSystem gameSystem)
        {
            m_gSys.Screen.Clear();
            m_gSys.Screen.BlendSrcAlpha();

            // 背景描画
            m_gSys.Screen.Blt(m_imgBg, 0, 0);

            // パーツ描画
            for (int i = 0; i < readableFlags.Length; i++)
            {
                if (!readableFlags[i])
                {
                    continue;
                }
                if ((int)CLASS.ACTOR == i)
                {
                    // アクターの足切り描画
                    m_gSys.Screen.Blt(m_seqParts.GetTexture(i), (int)OBJ_POS[i].X, (int)OBJ_POS[i].Y, rcActor);
                }
                else if ((int)CLASS.S02 == i)
                {
                    // シナリオ２の足きり描画
                    m_gSys.Screen.Blt(m_seqParts.GetTexture(i), (int)OBJ_POS[i].X, (int)OBJ_POS[i].Y, rc2nd);
                }
                else
                {
                    m_gSys.Screen.Blt(m_seqParts.GetTexture(i), (int)OBJ_POS[i].X, (int)OBJ_POS[i].Y);
                }
            }

            if (m_gameEnd)
            {
                m_gSys.Screen.Blt(m_imgLastMsg, LAST_MSG_X, LAST_MSG_Y);
            }

            m_gSys.Screen.SetColor(255, 255, 255);
            int offsetw = (int)m_imgTerm.Width / 2;
            int offseth = (int)m_imgTerm.Width / 2;

            // ターミネータ描画
            for (int i = 0; i < TERMI.Length; ++i)
            {

                if (!termiFlags[i])
                {
                    continue;
                }
                m_gSys.Screen.Blt(m_imgTerm, (int)TERMI[i].X - offsetw, (int)TERMI[i].Y - offseth);
            }

            textureGuiCtrl.OnPaint(m_gSys.Screen);

            // ボタン描画
            //btBack.OnDraw(info.screen);

            // シナリオ名描画
            m_gSys.Screen.Blt(m_titleNames.GetTexture(m_selectedIndex), TITLE_NAME_X, TITLE_NAME_Y);

            if (exitScene)
            {
                JumpScenarioViaTelop();
                return;
            }

            return;
        }

        /// <summary>
        /// 初期化処理
        /// </summary>
        private void OnInit()
        {
            //m_selectedIndex = (int)CLASS.S01;
            m_seqParts = m_gSys.SmartTextureLoader.LoadDefFile("img/sequence/parts.lst", false);
            m_titleNames = m_gSys.SmartTextureLoader.LoadDefFile("img/sequence/title_name.lst", false);


            InitFlags(m_gSys.UserInfo);

            if (m_gameEnd)
            {
                m_imgLastMsg = YamalibConst.CreateTexture("img/sequence/seq_actor2.png");
            }

            // 背景画像ロード
            m_imgBg = YamalibConst.CreateTexture("img/sequence/seq_bg.png");

            // 終端画像（×）ロード
            m_imgTerm = YamalibConst.CreateTexture("img/sequence/seq_trm.png");

            // ボタン初期化
            IinitTitleButtons();

            // 戻るボタン
            {
                FocusableTextureButton bt = new FocusableTextureButton("img/sequence/back_bt.lst", false);
                // イメージのオフセット
                bt.OnClick += delegate(IScreen scr, ControlContext cc)
                {
                    if (!showDialog)
                    {
                        // もどる！
                        m_gSys.SceneController.ReturnScene();
                        m_gSys.PlaySystemSE((int)GameSystem.SYS_SE.CLICK_TITLE_NEGATIVE);
                    }
                };
                textureGuiCtrl.AddFocusGUI(bt);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(bt, BACK_BT_X, BACK_BT_Y);
                //m_titleButtons.Add(ctrl);
                textureGuiCtrl.AddControl(ctrl);
            }

            // デフォルト選択
            textureGuiCtrl.Focus((int)CLASS.S01);
        }

        /// <summary>
        /// フラグ初期化
        /// </summary>
        /// <param name="userInfo"></param>
        private void InitFlags(UserInfo userInfo)
        {
            // とりあえず既読フラグをコピー
            List<bool> flags = new List<bool>();
            foreach (bool b in userInfo.ReadFlgs)
            {
                flags.Add(b);
            }
            this.readableFlags = null;
            this.termiFlags = null;

            /*/ ---------------------- DEBUG		
            flags[KyojinConst.ScenarioID.STORY01] = true;
            flags[KyojinConst.ScenarioID.STORY02_0] = true;
            flags[KyojinConst.ScenarioID.STORY02_1] = true;
            flags[KyojinConst.ScenarioID.STORY02_2] = true;
            flags[KyojinConst.ScenarioID.STORY03] = true;
            flags[KyojinConst.ScenarioID.STORY04] = true;
            flags[KyojinConst.ScenarioID.STORY05] = true;
            flags[KyojinConst.ScenarioID.STORY06] = true;
            flags[KyojinConst.ScenarioID.STORY07] = false;
            flags[KyojinConst.ScenarioID.KYOJIN01] = false;
            flags[KyojinConst.ScenarioID.KYOJIN02] = false;
            flags[KyojinConst.ScenarioID.KYOJIN03] = false;
            // ---------------------- DEBUG		/*/

            // 一個多いのはアウター
            this.readableFlags = new bool[flags.Count + 1];
            this.termiFlags = new bool[flags.Count + 1];

            // 最初はアウター
            this.readableFlags[(int)CLASS.ACTOR] = true;
            // シナリオ１は常に選択可能
            this.readableFlags[(int)CLASS.S01] = true;

            // シナリオ１が既読		
            if (flags[(int)KyojinConst.ScenarioID.STORY01])
            {
                this.readableFlags[(int)CLASS.S02] = true;
                this.termiFlags[(int)CLASS.S01] = true;
            }
            // 読まないが既読
            if (flags[(int)KyojinConst.ScenarioID.STORY02_1])
            {
                this.readableFlags[(int)CLASS.S03] = true;
            }
            // 読むが既読
            if (flags[(int)KyojinConst.ScenarioID.STORY02_2])
            {
                this.readableFlags[(int)CLASS.S06] = true;
            }
            // シナリオ３既読
            if (flags[(int)KyojinConst.ScenarioID.STORY03])
            {
                this.readableFlags[(int)CLASS.S04] = true;
                this.termiFlags[(int)CLASS.S03] = true;
            }
            // シナリオ４既読
            if (flags[(int)KyojinConst.ScenarioID.STORY04])
            {
                this.readableFlags[(int)CLASS.S05] = true;
                this.termiFlags[(int)CLASS.S04] = true;
            }
            // シナリオ５既読
            if (flags[(int)KyojinConst.ScenarioID.STORY05])
            {
                this.termiFlags[(int)CLASS.S05] = true;
            }
            // シナリオ６既読
            if (flags[(int)KyojinConst.ScenarioID.STORY06])
            {
                this.readableFlags[(int)CLASS.S07] = true;
                this.termiFlags[(int)CLASS.S06] = true;
            }
            // シナリオ７既読
            if (flags[(int)KyojinConst.ScenarioID.STORY07])
            {
                this.termiFlags[(int)CLASS.S07] = true;
            }

            // メインパートが既読
            if (flags[(int)KyojinConst.ScenarioID.STORY07] && flags[(int)KyojinConst.ScenarioID.STORY05])
            {
                this.readableFlags[(int)CLASS.K01] = true;
            }

            //this.readableFlags[(int)CLASS.S02] = true;
            //this.termiFlags[(int)CLASS.S01] = true;
            //this.readableFlags[(int)CLASS.S03] = true;
            //this.readableFlags[(int)CLASS.S06] = true;
            //this.readableFlags[(int)CLASS.S04] = true;
            //this.termiFlags[(int)CLASS.S03] = true;
            //this.readableFlags[(int)CLASS.S05] = true;
            //this.termiFlags[(int)CLASS.S04] = true;
            //this.termiFlags[(int)CLASS.S05] = true;
            //this.readableFlags[(int)CLASS.S07] = true;
            //this.termiFlags[(int)CLASS.S06] = true;
            //this.termiFlags[(int)CLASS.S07] = true;

            // すべての日記が既読
            if (readableFlags[(int)CLASS.S03] && readableFlags[(int)CLASS.S06])
            {
                this.termiFlags[(int)CLASS.S02] = true;
            }

            // KYOJIN01が既読
            if (flags[(int)KyojinConst.ScenarioID.KYOJIN01])
            {
                this.readableFlags[(int)CLASS.K02] = true;
                this.termiFlags[(int)CLASS.K01] = true;
            }
            // KYOJIN02が既読
            if (flags[(int)KyojinConst.ScenarioID.KYOJIN02])
            {
                this.readableFlags[(int)CLASS.K03] = true;
                this.termiFlags[(int)CLASS.K02] = true;
            }
            // KYOJIN03が既読
            if (flags[(int)KyojinConst.ScenarioID.KYOJIN03])
            {
                this.termiFlags[(int)CLASS.K03] = true;
                this.termiFlags[(int)CLASS.ACTOR] = true;
                this.m_gameEnd = true;
            }

            float tw = m_seqParts.GetTexture((int)CLASS.ACTOR).Width;
            float th = m_seqParts.GetTexture((int)CLASS.ACTOR).Height;

            // アウター表示
            this.rcActor.Left = 0;
            this.rcActor.Top = 0;
            this.rcActor.Right = tw;
            this.rcActor.Bottom = ACTOR_MAX[0];

            // 最大一致（去人シナリオ１がよめる）
            if (this.readableFlags[(int)CLASS.K01])
            {
                // 全部表示
                this.rcActor.Bottom = th;
            }
            else if (this.readableFlags[(int)CLASS.S03] || this.readableFlags[(int)CLASS.S06])
            {
                // シナリオ２が既読
                this.rcActor.Bottom = ACTOR_MAX[1];
            }

            // シナリオ２表示
            tw = m_seqParts.GetTexture((int)CLASS.S02).Width;
            th = m_seqParts.GetTexture((int)CLASS.S02).Width;

            this.rc2nd.Left = 0;
            this.rc2nd.Top = 0;
            this.rc2nd.Right = tw;
            this.rc2nd.Bottom = S02_MAX[0];

            if (this.readableFlags[(int)CLASS.S03] || readableFlags[(int)CLASS.S06])
            {
                this.rc2nd.Bottom = th;
            }
        }

        private bool jumpEyecatch = false;

        /// <summary>
        /// タイトルボタンの初期化
        /// </summary>
        private void IinitTitleButtons()
        {
            ctrlContext = new ControlContext();
            ctrlContext.MouseInput = m_gSys.MouseOriginal;
            ctrlContext.SmartTextureLoader = m_gSys.SmartTextureLoader;
            ctrlContext.SmartSoundLoader = m_gSys.SmartSoundLoader;
            ctrlContext.Param = new FocusableGUIParam(m_gSys.KeyDecolateMouse, m_gSys.Key);
            textureGuiCtrl.OnInit(ctrlContext);

            m_titleButtons.Add(CreateNullButton());

            string buttonDefFile = "img/sequence/title_bt.lst";
            for (int i = 0; i < TITLE_POS.Length; i++)
            {
                if (!readableFlags[i + 1])
                {
                    m_titleButtons.Add(CreateNullButton());
                    continue;
                }
                FocusableTextureButton bt = new FocusableTextureButton(buttonDefFile, false);
                // イメージのオフセット
                bt.LoaderOffset = i * 4;

                int myTextureIndex = i;
                bt.OnClick += delegate(IScreen scr, ControlContext cc)
                {
                    if ((int)KyojinConst.ScenarioID.KYOJIN01 > texStoryMap[myTextureIndex])
                    {
                        jumpEyecatch = true;
                        // メインパートではアイキャッチ画面へ
                        m_gSys.EyeCatcheSceneParam.CallTaskId = Scenes.Scenario;
                        m_gSys.EyeCatcheSceneParam.CallScenarioNo = (KyojinConst.ScenarioID)texStoryMap[myTextureIndex];
                    }
                    else
                    {
                        jumpEyecatch = false;
                        // 去人パートではシナリオテロップ画面へ
                        m_gSys.TelopParam.CallTaskId = Scenes.Scenario;
                        m_gSys.TelopParam.CallScenarioNo = (KyojinConst.ScenarioID)texStoryMap[myTextureIndex];
                    }

                    foreach (BookmarkData bookmarkData in m_gSys.UserInfo.BookmarkData)
                    {
                        if (bookmarkData.IsAutoBookmark && bookmarkData.IsUse)
                        {
                            showDialog = true;
                            m_gSys.ShowDialog(YesNoScene.TYPE.OVERWRITE);
                            break;
                        }
                        if (!showDialog)
                        {
                            JumpScenarioViaTelop();
                        }
                    }
                };

                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(bt, (int)TITLE_POS[i].X, (int)TITLE_POS[i].Y);
                m_titleButtons.Add(ctrl);
                textureGuiCtrl.AddControl(ctrl);

                textureGuiCtrl.AddFocusGUI(bt);
            }
        }


        /// <summary>
        /// シナリオ画面に遷移する
        /// </summary>
        /// <param name="p"></param>
        private void JumpScenarioViaTelop()
        {
            m_gSys.SceneController.ExitScene();
            if (jumpEyecatch)
            {
                m_gSys.SceneController.CallScene(Scenes.SelectorEyecatche);
            }
            else
            {
                m_gSys.SceneController.CallScene(Scenes.Telop);
            }
            m_gSys.CommonBgmLoader.StopBGMFade(1000);
            m_gSys.TelopParam.ScreenImg = YanesdkUtil.CopyGlFlameBuffer(m_gSys.Screen as Screen2DGl);
        }

        /// nullボタンを生成する
        TextureGUIControl.Control CreateNullButton()
        {
            FocusableTextureButton bt = new FocusableTextureButton(null);
            return new TextureGUIControl.Control(bt, 0, 0);
        }

    }
}
