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

namespace Kyojin.Scene.SaveLoad
{
    class BookmarkScene : TaskBase, IDisposable
    {
        #region 定数値

        /// ダイアログのタイプ
        private enum DIALOG_TYPE : int { LOAD, SAVABLE, LOAD_AUTO, SAVE };

        /// 画面フェード速度
        private const int FADE_SPEED = 3;

        /// 描画位置定義
        private const int AUTO_X = 227;
        private const int AUTO_Y = 195;
        private const int SLOT1_X = AUTO_X;
        private const int SLOT1_Y = 246;
        private const int SLOT2_X = AUTO_X;
        private const int SLOT2_Y = 299;
        private const int SLOT3_X = AUTO_X;
        private const int SLOT3_Y = 351;

        private readonly int[] SLOT_X = { AUTO_X, SLOT1_X, SLOT2_X, SLOT3_X };
        private readonly int[] SLOT_Y = { AUTO_Y, SLOT1_Y, SLOT2_Y, SLOT3_Y };

        private const int TEXNO_AUTO = 0;
        private const int TEXNO_01 = 1;
        private const int TEXNO_02 = 2;
        private const int TEXNO_03 = 3;

        /// 栞番号描画位置定義
        private const int BOOKMARK_NO_X = 0;
        private const int BOOKMARK_NO_Y = 54;

        private static readonly string BOOKMARKNO_MAIN_LST = "img/bookmark/bmno_main.lst";
        private static readonly string BOOKMARKNO_KYOJIN_LST = "img/bookmark/bmno_kyojin.lst";
        private static readonly string SCENARIO_NAME_LST = "img/bookmark/scenario_name.lst";
        private static readonly string MENU_BUTTON_LST = "img/bookmark/menu_bt.lst";

        /// シナリオ名描画位置定義
        private const int SCENARIO_NAME_X = 254;
        private const int SCENARIO_NAME_Y = 10;

        /// メニュー描画位置定義
        private const int FINISH_X = 0;
        private const int FINISH_Y = 424;
        private const int RETURN_X = 156;
        private const int RETURN_Y = FINISH_Y;
        private const int BACK_X = 539;
        private const int BACK_Y = 425;

        /// しおり詳細日付描画位置
        private const int DATE_X = 410;
        private const int DATE_Y = 73;

        /// しおり詳細ページ数描画位置
        private const int PAGE_X = 585;
        private const int PAGE_Y = DATE_Y;


        private enum TEXT_OFFSET { X = 272, Y = 95 };
        private const int MAX_TEXT_LINE = 3;
        private const int FONTSIZE = 20;
        private const int TEXTWIDTH = 340;

        private const float TEXT_RATE = 0.7f;

        private const int PAGE_FULL_LEN = 3;

        /// 背景用切抜き矩形
        private static readonly Rect BG_UPPER_RC = new Rect(0, 0, 640, 180);
        private static readonly Rect BG_MIDDLE_RC = new Rect(0, 180, 640, 415);
        private static readonly Rect BG_UNDER_RC = new Rect(0, 415, 640, 480);

        private const int OFFSET_X = 600;

        #endregion

        #region メンバフィールド

        private GameSystem m_gSys;
        private bool init = false;
        private bool m_fadeIn;
        private bool m_fadeOut;

        private RootCounterS m_alpha = new RootCounterS(0, 255, FADE_SPEED);

        // 刷新
        private readonly static FontRepository fontRep = new FontRepository(YamalibConst.FONT_REP_TEXTURE_FACTORY);
        //private DirectivityObjectManager m_dm;
        private readonly List<BookmarkView> m_bookmarks = new List<BookmarkView>();
        private BookmarkView m_targetBookmark;
        private FocusableTextureButton m_btFinish;
        private FocusableTextureButton m_btReturn;
        private FocusableTextureButton m_btBack;
        //private KeyGroup m_keyGroup;

        private ControlContext ctrlContext = new ControlContext();
        private FocusableTextureGUIControl textureGuiCtrl = new FocusableTextureGUIControl();
        private List<TextureGUIControl.Control> m_ctrls = new List<TextureGUIControl.Control>();

        private ITexture m_bg;
        private TextureLoader m_bookmarkNo;
        private TextureLoader m_scenarioName;

        private int m_focusSlotNo;
        private bool m_showDialog;
        private DIALOG_TYPE m_dialogType;
        private bool m_jumpSenerio;
        private bool m_jumpTitle;
        //private bool m_keyPush;
        private bool m_mainpartMode;
        private readonly IMouseInput m_mouse;

        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="gameSystem"></param>
        public BookmarkScene(GameSystem gameSystem)
        {
            m_gSys = gameSystem;
            m_mouse = m_gSys.KeyDecolateMouse;
        }


        #region IDisposable メンバ

        public void Dispose()
        {
            YamalibUtility.Dispose(m_bg);
        }

        #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)
        {
            //m_mouse.Update();
            m_gSys.Key.Update();
            m_gSys.KeyDecolateMouse.Update();
            m_gSys.CommonSeLoader.UpdateSE();

            if (m_showDialog)
            {
                m_mouse.Update();
            }
            if (!init)
            {
                OnInit();
                init = true;
            }

            // フェード用カウンタの動作
            if (m_fadeIn || m_fadeOut)
            {
                m_alpha.Inc();
                if (m_alpha.IsEnd)
                {
                    m_fadeIn = false;
                }
            }

            int i = 0;
            foreach (TextureGUIControl.Control ctrl in m_ctrls)
            {
                FocusableTextureButton bt = ctrl.Parts as FocusableTextureButton;
                if (null != bt && bt.IsHover)
                {
                    m_targetBookmark = m_bookmarks[i];
                    m_focusSlotNo = i;
                    break;
                }
                ++i;
            }

            if (null != m_targetBookmark)
            {
                m_targetBookmark.OnMove(m_gSys.Screen);
            }
            if (null != m_targetBookmark)
            {
                m_targetBookmark.OnMove(m_gSys.Screen);
            }

            // ダイアログ表示中
            if (m_showDialog && YesNoScene.CLICK.NO_CLICK != m_gSys.YesnoClickState)
            {
                if (DIALOG_TYPE.SAVABLE == m_dialogType)
                {
                    // セーブ出来る
                    switch ((int)m_gSys.YesnoClickState)
                    {
                        case 0:
                            ClickSave();
                            //Log.print("CLICK SAVE");
                            // セーブ
                            break;
                        case 1:
                            // ロード
                            ClickLoad();
                            //Log.print("CLICK LOAD");
                            break;
                        case 2:
                            // 削除
                            ClickRemove();
                            //Log.print("CLICK REMOVE");
                            break;
                        case 3:
                            // キャンセル
                            //Log.print("CLICK CANCEL");
                            break;
                        default:
                            //Log.printError("CLICK NO = %d", info.yesnoClick);
                            Debug.Assert(false, "不明なダイアログアイテムが選択された");
                            break;
                    }
                }
                else if (DIALOG_TYPE.LOAD == m_dialogType)
                {
                    // ロードのみ
                    switch ((int)m_gSys.YesnoClickState)
                    {
                        case 0:
                            // ロード
                            ClickLoad();
                            //Log.print("CLICK LOAD");
                            break;
                        case 1:
                            // 削除
                            ClickRemove();
                            //Log.print("CLICK REMOVE");
                            break;
                        case 2:
                            // キャンセル
                            //Log.print("CLICK CANCEL");
                            break;
                        default:
                            //Log.printError("CLICK NO = %d", info.yesnoClick);
                            Debug.Assert(false, "不明なダイアログアイテムが選択された");
                            break;
                    }
                }
                else if (DIALOG_TYPE.SAVE == m_dialogType)
                {
                    // セーブのみ
                    switch ((int)m_gSys.YesnoClickState)
                    {
                        case 0:
                            ClickSave();
                            //Log.print("CLICK SAVE");
                            // セーブ
                            break;
                        case 1:
                            // キャンセル
                            //Log.print("CLICK CANCEL");
                            break;
                        default:
                            //Log.printError("CLICK NO = %d", info.yesnoClick);
                            Debug.Assert(false, "不明なダイアログアイテムが選択された");
                            break;
                    }
                }
                else
                {
                    switch ((int)m_gSys.YesnoClickState)
                    {
                        case 0:
                            // ロード
                            ClickLoad();
                            //Log.print("CLICK LOAD");
                            break;
                        case 1:
                            // キャンセル
                            //Log.print("CLICK CANCEL");
                            break;
                        default:
                            //Log.printError("CLICK NO = %d", info.yesnoClick);
                            Debug.Assert(false, "不明なダイアログアイテムが選択された");
                            break;
                    }
                }
                m_showDialog = false;
            }

            // キー動作
            textureGuiCtrl.OnMoveFocus();

            // シーン制御
            if (m_fadeOut && m_alpha.IsEnd)
            {
                // シーン遷移
                if (m_gSys.FromTitleScene && m_jumpSenerio)
                {
                    // しおりの動作モードを変更
                    m_gSys.FromTitleScene = false;

                    // タイトルＢＧＭの停止
                    m_gSys.CommonBgmLoader.StopBGMFade(1000);

                    // 全てのシーンスタックを破棄して今までのことはなかったことにする！8(ﾟДﾟ)8
                    m_gSys.SceneController.ExitScene();
                    m_gSys.SceneController.JumpScene(Scenes.Scenario);

                    NullableMouseInput aKeyMouse = (NullableMouseInput)m_gSys.KeyDecolateMouse;
                    aKeyMouse.Enable();
                    return 0;
                }
                else if (m_jumpTitle)
                {

                    // すべてのサウンドを停止しておく
                    Sound.StopAll();

                    // 全てのシーンスタックを破棄して今までのことはなかったことにする！8(ﾟДﾟ)8
                    m_gSys.SceneController.ExitScene();
                    m_gSys.SceneController.JumpScene(Scenes.Startmenu);
                    NullableMouseInput aKeyMouse = (NullableMouseInput)m_gSys.KeyDecolateMouse;
                    aKeyMouse.Enable();
                    //Log.print("%s#OnMove: bookmark -> title jump", super.toString());
                    return 0;
                }
                else
                {
                    m_gSys.SceneController.ReturnScene();
                    NullableMouseInput aKeyMouse = (NullableMouseInput)m_gSys.KeyDecolateMouse;
                    aKeyMouse.Enable();
                    return 0;
                }
                //Log.print("%s#OnMove: Destroy IsFinish!", super.toString());
            }

            return 1;
        }

        /// <summary>
        /// セーブ処理
        /// </summary>
        private void ClickSave()
        {
            m_targetBookmark.BookmarkData.Text = m_gSys.BookmarkSceneParam.CurrentScenarioInfo.Text;
            m_targetBookmark.BookmarkData.IsUse = true;
            m_targetBookmark.BookmarkData.ScenarioInfo = m_gSys.BookmarkSceneParam.CurrentScenarioInfo.ScenarioInfo;
            m_targetBookmark.BookmarkData.SaveDate = DateTime.Now;
            m_gSys.ScenarioSceneParam.ScenarioInfo = null;
        }

        /// <summary>
        /// ロード処理
        /// </summary>
        private void ClickLoad()
        {
            if (m_gSys.BookmarkSceneParam.CurrentScenarioInfo == null)
            {
                m_gSys.BookmarkSceneParam.CurrentScenarioInfo = new CurrentInfo();
            }
            m_gSys.BookmarkSceneParam.CurrentScenarioInfo.ScenarioInfo = m_targetBookmark.BookmarkData.ScenarioInfo;

            // シナリオシーンにロード情報を渡す
            m_gSys.ScenarioSceneParam.IsReadTop = false;
            m_gSys.ScenarioSceneParam.ScenarioInfo = m_targetBookmark.BookmarkData.ScenarioInfo;

            m_targetBookmark.BookmarkData.Read = true;

            ReturnTask();
            m_jumpSenerio = true;
        }

        /// <summary>
        /// 削除処理
        /// </summary>
        private void ClickRemove()
        {
            m_targetBookmark.BookmarkData.IsUse = false;
        }

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

            // 背景の描画
            DrawBGMiddle(m_gSys.Screen);

            m_gSys.Screen.Blt(m_bg, 0, 0);

            // スフィア描画
            //m_dm.OnDraw(info.screen);

            DrawBGUpper(m_gSys.Screen);
            DarwBGUnder(m_gSys.Screen);

            // ブックマーク番号描画

            if (!m_showDialog)
            {
                m_gSys.Screen.Blt(m_bookmarkNo.GetTexture(m_focusSlotNo), BOOKMARK_NO_X, BOOKMARK_NO_Y);
            }

            // スロットの描画
            textureGuiCtrl.OnPaint(m_gSys.Screen);

            if (null != m_targetBookmark)
            {
                m_targetBookmark.OnPaint(m_gSys.Screen);
            }

        }

        /// 背景の上部を描画する
        void DrawBGUpper(IScreen screen)
        {
            DrawBG(screen, BG_UPPER_RC);
        }

        /// 背景の中央部を描画する
        void DrawBGMiddle(IScreen screen)
        {
            DrawBG(screen, BG_MIDDLE_RC);
        }

        /// 背景の下部を描画する
        void DarwBGUnder(IScreen screen)
        {
            DrawBG(screen, BG_UNDER_RC);
        }

        /// 指定した矩形部分だけ背景を描画する
        void DrawBG(IScreen screen, Rect rc)
        {
            screen.Blt(m_bg, (int)rc.Left, (int)rc.Top, rc);
        }


        /// <summary>
        /// 初期化処理
        /// </summary>
        private void OnInit()
        {
            m_fadeIn = true;
            m_fadeOut = false;

            foreach (BookmarkData bookmarkData in m_gSys.UserInfo.BookmarkData)
            {
                if (m_gSys.FromTitleScene)
                {
                }
            }

            FontLoader fl = m_gSys.SmartFontLoader.LoadDefFile("data/font.lst", false);
            BookmarkView.FontRep.SetLoader(fl, KyojinConst.SAVE_TEXT_FONT_NO);
            BookmarkView.FontRep.Max = 500;

            foreach (BookmarkData bkData in m_gSys.UserInfo.BookmarkData)
            {
                BookmarkView bv = new BookmarkView();
                bv.BookmarkData = bkData;
                m_bookmarks.Add(bv);
                bv.ScenarioName = m_gSys.SmartTextureLoader.LoadDefFile(SCENARIO_NAME_LST, false);
            }

            m_mainpartMode = false;

            // スロットの初期化
            InitSlotBt(m_mouse);
            // テクスチャの初期化
            InitTexture();

            textureGuiCtrl.Focus(0);
        }

        /// <summary>
        /// 使用するテクスチャの初期化
        /// </summary>
        private void InitTexture()
        {
            // シナリオ名・メイン、KYOJIN非依存
            m_scenarioName = m_gSys.SmartTextureLoader.LoadDefFile(SCENARIO_NAME_LST, false);

            if (m_mainpartMode)
            {
                // メインパート
                m_bg = YamalibConst.CreateTexture("img/bookmark/bm_bg_a.png");
                m_bookmarkNo = m_gSys.SmartTextureLoader.LoadDefFile(BOOKMARKNO_MAIN_LST, false);
            }
            else
            {
                // 去人パート
                m_bg = YamalibConst.CreateTexture("img/bookmark/bm_bg_b.png");
                m_bookmarkNo = m_gSys.SmartTextureLoader.LoadDefFile(BOOKMARKNO_KYOJIN_LST, false);
            }

            {
                m_btFinish = new FocusableTextureButton(MENU_BUTTON_LST, false);
                m_btFinish.LoaderOffset = 0;
                m_btFinish.OnClick += delegate(IScreen scr, ControlContext cc)
                {
                    if (!m_fadeIn && !m_fadeOut)
                    {
                        // セーブしておく
                        m_gSys.SaveUserInfo(KyojinConst.SAVE_HEADER_FILE);

                        m_gSys.ShowDialog(YesNoScene.TYPE.FINISH);
                        m_gSys.PlaySystemSE((int)GameSystem.SYS_SE.CLICK_TITLE_NEGATIVE);
                    }
                };
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btFinish, FINISH_X, FINISH_Y);
                textureGuiCtrl.AddControl(ctrl);
                // キーグループに登録
                textureGuiCtrl.AddFocusGUI(m_btFinish);

            }

            // 遷移元がタイトル画面でない場合は、タイトル画面に戻るを描画
            if (!m_gSys.FromTitleScene)
            {
                m_btReturn = new FocusableTextureButton(MENU_BUTTON_LST, false);
                m_btReturn.LoaderOffset = 4;
                m_btReturn.OnClick += delegate(IScreen scr, ControlContext cc)
                {
                    // セーブしておく
                    m_gSys.SaveUserInfo(KyojinConst.SAVE_HEADER_FILE);

                    if (!m_fadeIn && !m_fadeOut)
                    {
                        ReturnTask();
                        m_jumpTitle = true;
                    }
                };
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btReturn, RETURN_X, RETURN_Y);
                textureGuiCtrl.AddControl(ctrl);
                // キーグループに登録
                textureGuiCtrl.AddFocusGUI(m_btReturn);
            }

            {
                m_btBack = new FocusableTextureButton(MENU_BUTTON_LST, false);
                m_btBack.LoaderOffset = 8;
                m_btBack.OnClick += delegate(IScreen scr, ControlContext cc)
                {
                    if (!m_fadeIn && !m_fadeOut)
                    {
                        m_gSys.ScenarioSceneParam.ScenarioInfo = null;
                        ReturnTask();
                    }
                };
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btBack, BACK_X, BACK_Y);
                textureGuiCtrl.AddControl(ctrl);
                // キーグループに登録
                textureGuiCtrl.AddFocusGUI(m_btBack);
            }
        }

        /// <summary>
        /// タスクを終了して前のシーンに帰る準備
        /// </summary>
        private void ReturnTask()
        {
            m_fadeOut = true;
            m_alpha.Set(255, 0, FADE_SPEED);

            NullableMouseInput aKeyMouse = (NullableMouseInput)m_gSys.KeyDecolateMouse;
            aKeyMouse.Disable();
        }

        /// <summary>
        /// セーブスロットの初期化
        /// </summary>
        /// <param name="m_mouse"></param>
        private void InitSlotBt(IMouseInput m_mouse)
        {
            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);

            for (int i = 0; i < 4; i++)
            {
                FocusableTextureButton bt = new FocusableTextureButton("img/bookmark/slot_bt.lst", false);
                // イメージのオフセット
                bt.LoaderOffset = i * 4;
                BookmarkView myView = m_bookmarks[i];
                bt.OnClick += delegate(IScreen scr, ControlContext cc)
                    {
                        if (!m_showDialog)
                        {
                            m_targetBookmark = myView;
                            ShowBookmarkDialog();
                        }
                    };

                //SetDefaultButtonState(bt, i);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(bt, SLOT_X[i], SLOT_Y[i]);
                textureGuiCtrl.AddControl(ctrl);
                m_ctrls.Add(ctrl);

                // キーグループに登録
                textureGuiCtrl.AddFocusGUI(bt);
            }
        }

        /// <summary>
        /// ブックマークようのダイアログを開く
        /// </summary>
        private void ShowBookmarkDialog()
        {
            if (m_gSys.FromTitleScene && !m_targetBookmark.BookmarkData.IsUse)
            {
                m_gSys.PlaySystemSE((int)GameSystem.SYS_SE.CLICK_TITLE_NEGATIVE);
                return;
            }
            if (m_targetBookmark.BookmarkData.IsAutoBookmark)
            {
                m_gSys.ShowDialog(YesNoScene.TYPE.LOAD_AUTO);
                m_dialogType = DIALOG_TYPE.LOAD_AUTO;
            }
            else if (!m_gSys.FromTitleScene && !m_targetBookmark.BookmarkData.IsUse)
            {
                m_gSys.ShowDialog(YesNoScene.TYPE.SAVE_ONLY);
                m_dialogType = DIALOG_TYPE.SAVE;
            }
            else if (!m_gSys.FromTitleScene)
            {
                m_gSys.ShowDialog(YesNoScene.TYPE.SAVE);
                m_dialogType = DIALOG_TYPE.SAVABLE;
            }
            else
            {
                m_gSys.ShowDialog(YesNoScene.TYPE.LOAD);
                m_dialogType = DIALOG_TYPE.LOAD;
            }
            m_showDialog = true;
        }

        private TextureButton.MouseEvent GetButtonEvent(int slotNo)
        {
            switch (slotNo)
            {
                case 0:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        m_targetBookmark = m_bookmarks[3];
                    };
                case 1:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        m_targetBookmark = m_bookmarks[0];
                    };
                case 2:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        m_targetBookmark = m_bookmarks[1];
                    };
                case 3:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        m_targetBookmark = m_bookmarks[2];
                    };
                default:
                    return null;
            }
        }
    }
}
