using System;
using System.Collections.Generic;
using System.Text;
using Yanesdk.Draw;
using Yamalib.Input;
using Yamalib.Util;
using Yanesdk.Sound;
using Yanesdk.Input;
using Yamalib.GUI;
using Yamalib;
using Yanesdk.Timer;
using Yanesdk.GUIParts;
using System.Diagnostics;
using Yamalib.Draw;
using Yamalib.Scenario;

namespace Kyojin.Component.MusicRoom
{

    public abstract class ComponentBase
    {
        #region 定数値

        protected static readonly string C_PROP_KEY_TTL_POSX = "title_posx";
        protected static readonly string C_PROP_KEY_TTL_POSY = "title_posy";
        protected static readonly string C_PROP_KEY_DSC_POSX = "disc_posx";
        protected static readonly string C_PROP_KEY_DSC_POSY = "disc_posy";
        protected static readonly string C_PROP_KEY_MAIN_POSX = "main_posx";
        protected static readonly string C_PROP_KEY_MAIN_POSY = "main_posy";
        protected static readonly string C_PROP_KEY_PL_POSX = "pl_posx";
        protected static readonly string C_PROP_KEY_PL_POSY = "pl_posy";
        protected static readonly string C_PROP_KEY_PL_SZX = "pl_sizex";
        protected static readonly string C_PROP_KEY_PL_SZY = "pl_sizey";
        protected static readonly string C_PROP_KEY_BACK_BT_X = "back_bt_x";
        protected static readonly string C_PROP_KEY_BACK_BT_Y = "back_bt_y";

        #endregion

        #region メンバフィールド

        protected IMouseInput m_mouse;
        protected ITexture m_main;	//!< 基本画像
        protected int m_dx;	// 基準となる描画位置
        protected int m_dy;

        private static Properties m_propGeneral;

        #endregion

        public abstract void OnMove(IScreen screen);
        public abstract void OnDraw(IScreen screen);

        /// 基本となる下地テクスチャの設定
        public void SetMainTexture(ITexture t_)
        {
            this.m_main = t_;
        }

        /// 描画位置の設定
        public void SetDrawPos(int x_, int y_)
        {
            this.m_dx = x_;
            this.m_dy = y_;
        }

        /// 描画位置の取得
        public void GetDrawPos(out int x_, out int y_)
        {
            x_ = this.m_dx;
            y_ = this.m_dy;
        }

        /// マウスの設定
        public void SetMouse(IMouseInput m_)
        {
            this.m_mouse = m_;
        }

        /// このタスクの終了リクエスト
        public virtual bool IsExitReq()
        {
            return false;
        }

        /// コンストラクタ
        public ComponentBase(IMouseInput m_)
        {
            SetMouse(m_);
        }

        /// 共通プロパティの取得
        protected static Properties GetGenProp()
        {
            if (m_propGeneral == null)
            {
                m_propGeneral = Properties.GetInstance("img2/music/skin/basic/general.txt");
            }
            return m_propGeneral;
        }
    }

    public class MainParts : ComponentBase
    {
        #region 定数値

        private static readonly string C_PROP_KEY_PRE_X = "prev_offsetx";
        private static readonly string C_PROP_KEY_PRE_Y = "prev_offsety";
        private static readonly string C_PROP_KEY_PLAY_X = "play_offsetx";
        private static readonly string C_PROP_KEY_PLAY_Y = "play_offsety";
        private static readonly string C_PROP_KEY_PAUSE_X = "pause_offsetx";
        private static readonly string C_PROP_KEY_PAUSE_Y = "pause_offsety";
        private static readonly string C_PROP_KEY_STOP_X = "stop_offsetx";
        private static readonly string C_PROP_KEY_STOP_Y = "stop_offsety";
        private static readonly string C_PROP_KEY_NEXT_X = "next_offsetx";
        private static readonly string C_PROP_KEY_NEXT_Y = "next_offsety";
        private static readonly string C_PROP_KEY_REPEART_X = "repeat_offsetx";
        private static readonly string C_PROP_KEY_REPEART_Y = "repeat_offsety";
        private static readonly string C_PROP_KEY_SHUFF_X = "shuff_offsetx";
        private static readonly string C_PROP_KEY_SHUFF_Y = "shuff_offsety";
        private static readonly string C_PROP_KEY_NUM_X = "num_offsetx";
        private static readonly string C_PROP_KEY_NUM_Y = "num_offsety";
        private static readonly string C_PROP_KEY_VOL_X = "vol_offsetx";
        private static readonly string C_PROP_KEY_VOL_Y = "vol_offsety";
        private static readonly string C_PROP_KEY_VOL_BAR_X = "vol_bar_offsetx";
        private static readonly string C_PROP_KEY_VOL_BAR_Y = "vol_bar_offsety";
        private static readonly string C_PROP_KEY_VOL_WIDTH = "vol_slide_width";

        /// <summary>
        /// ボタンの名前付きインデックス
        /// </summary>
        private enum BT_TYPE : int
        {
            PREV = 0,
            PLAY,
            PAUSE,
            STOP,
            NEXT,
            REPEAT,
            SHUFFLE,
            RETURN,
            VOL,
        };

        /// <summary>
        /// リピート状態
        /// </summary>
        private enum REP_TYPE : int
        {
            NO = 0,	// なし
            //TRACK,	// トラック
            ALL		// 前曲
        };

        #endregion

        #region メンバフィールド

        /** キーのコレクション */
        private static List<string> PROP_KEYS = new List<string>();
        private readonly Yanesdk.Math.Rand rand = new Yanesdk.Math.Rand();			//!< シャッフル用

        private FocusableTextureGUIControl textureGuiCtrl = new FocusableTextureGUIControl();
        private ControlContext ctrlContext;
        private List<TextureGUIControl.Control> m_buttons = new List<TextureGUIControl.Control>();
        private Properties m_prop;			//!< プロパティ
        private SoundLoader m_bgm;			//!< 再生する曲
        private bool init;
        private bool exit;					//!< 終了要請
        private bool m_pause;				//!< 一時停止中か
        private FixTimer m_timer;				//!< 疑似再生タイムを行う
        //private bool m_loading;				//!< ローダースレッドでロード中
        private readonly int bgmNum;

        //private SpriteLoader m_sl;
        //private SpriteEx m_sprite;			//!< 数字
        private NumberCounter[] timeCounters;
        private TextureLoader numberTextures;
        private int m_numx;					//!< 数字描画オフセット
        private int m_numy;

        private int m_playReq = -1;			//!< 外部からの再生リクエスト
        private int m_playNoReal = -1;
        private int m_loop = 0;				//!< ループならば-1
        private float m_vol;

        private readonly List<int> m_playNo = new List<int>();				//!< 曲の再生順が格納されている配列
        private int m_selNo;				//!< 現在選択している曲インデックス

        private bool m_shuff;				//!< シャッフルステート
        private int m_repeatState;			//!< リピートの状態（オフ、トラック、全曲）

        private IKeyInput m_keyInput;
        private Slider m_volBar;			//!< ボリュームバー

        private FocusableTextureButton m_btPrev;			//!< 前曲
        private FocusableTextureButton m_btPlay;			//!< 再生
        private FocusableTextureButton m_btPause;		//!< 一時停止
        private FocusableTextureButton m_btStop;			//!< 停止
        private FocusableTextureButton m_btNext;			//!< 次曲
        private FocusableTextureButton m_btRepeat;		//!< リピート
        private FocusableTextureButton m_btShuffle;		//!< シャッフル
        private FocusableTextureButton m_btBack;			//!< タイトル画面へ戻る

        //private GUIButton[] m_Bts;			//!< ボタンのコンテナとして使用

        #endregion

        /// <summary>
        /// 静的コンストラクタ
        /// </summary>
        static MainParts()
        {
            PROP_KEYS.Add(C_PROP_KEY_PRE_X);
            PROP_KEYS.Add(C_PROP_KEY_PRE_Y);
            PROP_KEYS.Add(C_PROP_KEY_PLAY_X);
            PROP_KEYS.Add(C_PROP_KEY_PLAY_Y);
            PROP_KEYS.Add(C_PROP_KEY_PAUSE_X);
            PROP_KEYS.Add(C_PROP_KEY_PAUSE_Y);
            PROP_KEYS.Add(C_PROP_KEY_STOP_X);
            PROP_KEYS.Add(C_PROP_KEY_STOP_Y);
            PROP_KEYS.Add(C_PROP_KEY_NEXT_X);
            PROP_KEYS.Add(C_PROP_KEY_NEXT_Y);
            PROP_KEYS.Add(C_PROP_KEY_REPEART_X);
            PROP_KEYS.Add(C_PROP_KEY_REPEART_Y);
            PROP_KEYS.Add(C_PROP_KEY_SHUFF_X);
            PROP_KEYS.Add(C_PROP_KEY_SHUFF_Y);
            PROP_KEYS.Add(C_PROP_KEY_VOL_X);
            PROP_KEYS.Add(C_PROP_KEY_VOL_Y);
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MainParts(IMouseInput m_, MouseInput mouse, IKeyInput key, SmartTextureLoader st, SmartSoundLoader ss, int bgmNum)
            : base(m_)
        {
            m_repeatState = (int)REP_TYPE.NO;
            m_timer = new FixTimer();
            m_timer.Reset();
            rand.Randomize();
            this.bgmNum = bgmNum;

            ctrlContext = new ControlContext();
            ctrlContext.MouseInput = mouse;
            ctrlContext.SmartTextureLoader = st;
            ctrlContext.SmartSoundLoader = ss;
            ctrlContext.Param = new FocusableGUIParam(m_, key);
            textureGuiCtrl.OnInit(ctrlContext);

            // ナンバー
            numberTextures = st.LoadDefFile("img2/music/skin/basic/num.lst", false);
            timeCounters = new NumberCounter[5];
            for (int i = 0; i < timeCounters.Length; i++)
            {
                timeCounters[i] = new NumberCounter(numberTextures, 1);
            }

        }

        public override void OnMove(IScreen screen)
        {
            if (!init)
            {
                OnInit();
            }
            m_timer.Update();

            if (m_volBar.IsModifiy())
            {
                m_vol = m_volBar.GetSlidePos();

                // 今なってる！
                if (-1 != m_playNoReal)
                {
                    this.m_bgm.GetSound(m_playNoReal).Volume = m_vol;
                }
            }

            textureGuiCtrl.OnMoveFocus();

            // 外部からの再生要求！（プレイリストからとか...）
            if (-1 != m_playReq)
            {
                int found = -1;
                int i = 0;
                foreach (int num in m_playNo)
                {
                    if (num == m_playReq)
                    {
                        found = i;
                        break;
                    }
                    ++i;
                }
                if (-1 != found)
                {
                    m_selNo = found;
                    m_btPlay.OnClick(screen, ctrlContext);
                }

                m_playReq = -1;
            }

            // なってるのに止まってる次へ
            if (-1 != m_playNoReal && !m_pause)
            {
                if (!this.m_bgm.IsPlaying(m_playNoReal))
                {
                    m_btNext.OnClick(screen, ctrlContext);
                }
            }

        }

        public override void OnDraw(IScreen screen)
        {
            // プレイヤー
            screen.Blt(m_main, m_dx, m_dy);

            // タイマ秒数
            if (-1 != m_playNoReal)
            {
                // mmss の列
                List<int> nums = new List<int>();
                int time = (int)m_timer.Time / 1000;
                int mm = time / 60;
                int ss = time % 60;

                nums.Add(mm / 10);
                nums.Add(mm % 10);
                nums.Add(10);			// これコロンね
                nums.Add(ss / 10);
                nums.Add(ss % 10);

                int i = 0;
                foreach (int dire in nums)
                {
                    if (i >= timeCounters.Length)
                    {
                        break;
                    }
                    if (dire == 10)
                    {
                        screen.Blt(numberTextures.GetTexture(10), timeCounters[i].X + 15, timeCounters[i].Y);
                    }
                    else
                    {
                        timeCounters[i].Number = dire;
                        timeCounters[i].OnPaint(screen);
                    }
                    //m_sprite.blt( screen, m_dx + m_numx + i * 20, m_dy + m_numy );
                    ++i;
                }
            }

            textureGuiCtrl.OnPaint(screen);

            // ボリュームバー描画
            m_volBar.OnDraw(screen);
        }

        /// 終了要請
        public override bool IsExitReq()
        {
            return exit;
        }

        /// <summary>
        /// 再生全曲リストを設定
        /// </summary>
        /// <param name="sl_"></param>
        public void SetSoundLoader(SoundLoader sl_)
        {
            this.m_bgm = sl_;
        }

        /// <summary>
        /// 再生番号を取得
        /// </summary>
        /// <returns></returns>
        public int GetPlayNum()
        {
            return m_playNo[m_selNo];
        }

        /// <summary>
        /// 外部からも再生要求を受け付けるのだ
        /// </summary>
        /// <param name="n"></param>
        public void SetPlayNum(int n)
        {
            this.m_playReq = n;
        }

        /// 外部とのインターフェース
        public void SetVolume(int n)
        {
            m_volBar.SetSlidePos((float)n / 100.0f);
            this.m_vol = (int)(100 * m_volBar.GetSlidePos());
        }
        /// ボリュームの取得
        public int GetVolume()
        {
            return (int)(100 * m_volBar.GetSlidePos());
        }

        public void SetInputDevice(IKeyInput key, IMouseInput mouse)
        {
            m_keyInput = key;
            m_mouse = mouse;
        }

        /// <summary>
        /// 最後に再生した（している）曲番を返す
        /// </summary>
        /// <returns></returns>
        public int GetLastPlayNo()
        {
            if (-1 != m_playNoReal)
            {
                return m_playNoReal;
            }
            else
            {
                return m_playNo[m_selNo];
            }
        }

        #region 非公開メンバ

        /// <summary>
        /// 初期化処理
        /// </summary>
        private void OnInit()
        {
            Properties propGen = GetGenProp();
            m_dx = (int)propGen.GetPropertyNum(C_PROP_KEY_MAIN_POSX, 0);
            m_dy = (int)propGen.GetPropertyNum(C_PROP_KEY_MAIN_POSY, 0);

            m_prop = Properties.GetInstance("img2/music/skin/basic/main.txt");
            m_main = YamalibConst.CreateTexture("img2/music/skin/basic/main.png");

            // 再生リスト構築
            int maxNo = bgmNum;
            m_playNo.Clear();
            for (int i = 0; i < maxNo; ++i)
            {
                m_playNo.Add(i);
            }


            // タイトル画面へ戻るボタン表示位置を手動設定
            int rx = (int)propGen.GetPropertyNum(C_PROP_KEY_BACK_BT_X, 0);
            int ry = (int)propGen.GetPropertyNum(C_PROP_KEY_BACK_BT_Y, 0);
            //m_btBack.SetXY(m_dx + rx, m_dy + ry);

            // ボリューム
            CreateVolBar();

            // ボタン構築
            CreateButton();


            // 秒数用スプライト
            //m_sl = new SpriteLoader();
            //m_sprite = new SpriteEx();

            //m_sl.load("img2/music/skin/basic/num.sdf");
            //m_sprite.setSprite( m_sl.getSprite() );

            m_numx = (int)m_prop.GetPropertyNum(C_PROP_KEY_NUM_X, 0);
            m_numy = (int)m_prop.GetPropertyNum(C_PROP_KEY_NUM_Y, 0);

            for (int i = 0; i < timeCounters.Length; i++)
            {
                timeCounters[i].X = m_dx + m_numx + i * 15;
                timeCounters[i].Y = m_dy + m_numy;
            }

            //Log.print("mainCtl init IsFinish");

            init = true;
        }

        /// 再生リストをシャッフルする
        private void RandomizeList()
        {
            int size = m_playNo.Count;
            for (int i = 0; i < size * 10; ++i)
            {
                int index1 = rand.GetRand(size);
                int index2 = rand.GetRand(size);
                int tmp = m_playNo[index1];
                m_playNo[index1] = m_playNo[index2];
                m_playNo[index2] = tmp;
            }
        }

        /// 再生リストを正規化する
        void NormalizeList()
        {
            int size = m_playNo.Count;
            m_playNo.Clear();
            for (int i = 0; i < size; ++i)
            {
                m_playNo.Add(i);
            }
        }

        private void CreateButton()
        {

            string buttonDefFile = "img2/music/skin/basic/player.lst";
            List<FocusableTextureButton> btList = new List<FocusableTextureButton>();

            m_btPrev = new FocusableTextureButton(buttonDefFile, false);
            m_btPlay = new FocusableTextureButton(buttonDefFile, false);
            m_btPause = new FocusableTextureButton(buttonDefFile, false);
            m_btStop = new FocusableTextureButton(buttonDefFile, false);
            m_btNext = new FocusableTextureButton(buttonDefFile, false);

            btList.Add(m_btPrev);
            btList.Add(m_btPlay);
            btList.Add(m_btPause);
            btList.Add(m_btStop);
            btList.Add(m_btNext);

            int loopCount = 0;
            foreach (FocusableTextureButton bt in btList)
            {
                bt.LoaderOffset = loopCount * 3;
                bt.OnClick += GetButtonEvent(loopCount);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(bt, 0, 0);
                textureGuiCtrl.AddControl(ctrl);
                m_buttons.Add(ctrl);

                textureGuiCtrl.AddFocusGUI(bt);
                ++loopCount;
            }

            // ボリューム
            textureGuiCtrl.AddFocusGUI(m_volBar as FocusableTextureGUI);

            {
                // シャッフル２段階
                m_btShuffle = new FocusableTextureButton(buttonDefFile, false);
                m_btShuffle.LoaderOffset = 21;
                m_btShuffle.OnClick += GetButtonEvent(6);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btShuffle, 0, 0);
                textureGuiCtrl.AddControl(ctrl);
                m_buttons.Add(ctrl);
                textureGuiCtrl.AddFocusGUI(m_btShuffle);
            }

            {
                // リピート　３段階
                m_btRepeat = new FocusableTextureButton(buttonDefFile, false);
                m_btRepeat.LoaderOffset = 15;
                m_btRepeat.OnClick += GetButtonEvent(5);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btRepeat, 0, 0);
                textureGuiCtrl.AddControl(ctrl);
                m_buttons.Add(ctrl);
                textureGuiCtrl.AddFocusGUI(m_btRepeat);
            }


            {
                // タイトル画面に戻る
                int rx = (int)GetGenProp().GetPropertyNum(C_PROP_KEY_BACK_BT_X, 0);
                int ry = (int)GetGenProp().GetPropertyNum(C_PROP_KEY_BACK_BT_Y, 0);
                m_btBack = new FocusableTextureButton(buttonDefFile, false);
                m_btBack.LoaderOffset = 27;
                m_btBack.OnClick += GetButtonEvent(7);
                TextureGUIControl.Control ctrl = new TextureGUIControl.Control(m_btBack, m_dx + rx, m_dy + ry);
                textureGuiCtrl.AddControl(ctrl);
                //                m_buttons.Add(ctrl);
                textureGuiCtrl.AddFocusGUI(m_btBack);
            }

            // 描画位置
            List<int> points = GetBtPos();
            for (int i = 0; i < m_buttons.Count; i++)
            {
                m_buttons[i].SetXY(m_dx + points[i * 2], m_dy + points[i * 2 + 1]);
            }

        }

        /// <summary>
        /// 各ボタンコントロールに付与するデリゲードを返却する
        /// </summary>
        /// <param name="buttonId"></param>
        /// <returns></returns>
        private TextureButton.MouseEvent GetButtonEvent(int buttonId)
        {
            switch ((BT_TYPE)buttonId)
            {
                case BT_TYPE.PREV:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        // 一時停止解除
                        m_pause = false;

                        int oldNo = m_selNo;
                        --m_selNo;
                        if (m_selNo < 0)
                        {
                            // 全曲リピートならば最後尾へ
                            if (m_repeatState == (int)REP_TYPE.ALL)
                            {
                                m_selNo = m_playNo.Count - 1;
                            }
                            else
                            {
                                m_selNo = 0;
                            }
                        }

                        // 前にBGMが再生されていたならば
                        if (-1 != m_playNoReal)
                        {
                            //this.m_bgm.Get( m_playNo[oldNo] ).Stop();
                            this.m_bgm.StopBGM();
                            // 新しい曲を再生する
                            this.m_bgm.GetSound(m_playNo[m_selNo]).Loop = m_loop;
                            this.m_bgm.PlayBGM(m_playNo[m_selNo]);
                            this.m_bgm.GetSound(m_playNo[m_selNo]).Volume = m_vol;
                            m_playNoReal = m_playNo[m_selNo];
                            m_timer.Reset();
                            //m_timer.Pause();
                            //m_loading = true;
                        }
                    };

                case BT_TYPE.PLAY:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        if (m_pause && -1 != m_playNoReal)
                        {
                            // 一時停止から再開
                            this.m_bgm.GetSound(m_playNoReal).Resume();
                            m_timer.Resume();
                            m_pause = false;
                        }
                        else
                        {
                            // 通常再生
                            this.m_bgm.StopBGM();
                            if (-1 != m_playNoReal)
                            {
                                this.m_bgm.StopBGM();
                            }
                            if (!this.m_bgm.IsPlaying(m_playNo[m_selNo]))
                            {
                                this.m_bgm.GetSound(m_playNo[m_selNo]).Loop = m_loop;
                                this.m_bgm.PlayBGM(m_playNo[m_selNo]);
                                this.m_bgm.GetSound(m_playNo[m_selNo]).Volume = m_vol;
                                m_playNoReal = m_playNo[m_selNo];
                                m_timer.Reset();
                                //m_timer.Pause();
                                //m_loading = true;
                            }

                        }
                    };

                case BT_TYPE.PAUSE:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        if (-1 != m_playNoReal)
                        {
                            if (!m_pause)
                            {
                                // 一時停止になる
                                this.m_bgm.GetSound(m_playNoReal).Pause();
                                m_timer.Pause();
                                m_pause = true;
                            }
                            else
                            {
                                // 再開する
                                this.m_bgm.GetSound(m_playNoReal).Resume();
                                m_timer.Resume();
                                m_pause = false;
                            }
                        }
                    };

                case BT_TYPE.STOP:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        // 一時停止解除
                        m_pause = false;
                        if (-1 != m_playNoReal)
                        {
                            this.m_bgm.StopBGM();
                        }
                        m_playNoReal = -1;
                    };
                case BT_TYPE.NEXT:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        // 一時停止解除
                        m_pause = false;
                        int oldNo = m_selNo;
                        ++m_selNo;
                        if (m_selNo >= m_playNo.Count)
                        {
                            // 全曲リピートならば頭へ
                            if (m_repeatState == (int)REP_TYPE.ALL)
                            {
                                m_selNo = 0;
                            }
                            else
                            {
                                m_selNo = m_playNo.Count - 1;
                            }
                        }

                        // 前にBGMが再生されていたならば
                        if (-1 != m_playNoReal)
                        {
                            this.m_bgm.StopBGM();
                            // 新しい曲を再生する
                            this.m_bgm.GetSound(m_playNo[m_selNo]).Loop = m_loop;
                            this.m_bgm.GetSound(m_playNo[m_selNo]).Volume = m_vol;
                            this.m_bgm.PlayBGM(m_playNo[m_selNo]);
                            m_playNoReal = m_playNo[m_selNo];
                            m_timer.Reset();
                            //m_timer.Pause();
                            //m_loading = true;
                        }

                    };
                case BT_TYPE.REPEAT:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        ++m_repeatState;
                        if (m_repeatState > (int)REP_TYPE.ALL)
                        {
                            m_repeatState = (int)REP_TYPE.NO;
                        }

                        if ((int)REP_TYPE.ALL == m_repeatState)
                        {
                            m_btRepeat.LoaderOffset += 3;
                        }
                        else
                        {
                            m_btRepeat.LoaderOffset -= 3;
                        }
                    };

                case BT_TYPE.SHUFFLE:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        m_shuff = !m_shuff;

                        int no = m_playNo[m_selNo];

                        // シャッフル処理
                        if (m_shuff)
                        {
                            RandomizeList();
                        }
                        else
                        {
                            NormalizeList();
                        }

                        int i = 0;
                        foreach (int num in m_playNo)
                        {
                            if (num == no)
                            {
                                m_selNo = i;
                                break;
                            }
                            ++i;
                        }

                        if (m_shuff)
                        {
                            m_btShuffle.LoaderOffset += 3;
                        }
                        else
                        {
                            m_btShuffle.LoaderOffset -= 3;
                        }
                    };
                case BT_TYPE.RETURN:
                    return delegate(IScreen scr, ControlContext cc)
                    {
                        this.m_bgm.StopBGM();
                        m_playNoReal = -1;
                        exit = true;
                    };
                default:
                    Debug.Assert(false);
                    return null;
            }
        }

        /// <summary>
        /// 音量バーの構築
        /// </summary>
        private void CreateVolBar()
        {
            // プロパティより取得
            int vlength = (int)m_prop.GetPropertyNum(C_PROP_KEY_VOL_WIDTH, 100);
            int box = (int)m_prop.GetPropertyNum(C_PROP_KEY_VOL_BAR_X, 0);
            int boy = (int)m_prop.GetPropertyNum(C_PROP_KEY_VOL_BAR_Y, 0);
            int ox = (int)m_prop.GetPropertyNum(C_PROP_KEY_VOL_X, 0);
            int oy = (int)m_prop.GetPropertyNum(C_PROP_KEY_VOL_Y, 0);

            // 音量バー
            m_volBar = new Slider();
            m_volBar.SetKey(m_keyInput);
            m_volBar.SetXY(m_dx + ox, m_dy + oy);

            ITexture tmpBase = YamalibConst.CreateTexture("img2/music/skin/basic/base.png");
            ITexture tmpBar = YamalibConst.CreateTexture("img2/music/skin/basic/bar.png");

            m_volBar.SetBaseTexture(tmpBase);
            m_volBar.SetBarTexture(tmpBar);
            m_volBar.SetLength(vlength);
            m_volBar.SetSliderOffset(box, boy);

            textureGuiCtrl.AddControl(m_volBar, m_dx + ox, m_dy + oy);
        }

        private List<int> GetBtPos()
        {
            List<int> values = new List<int>();
            foreach (string key in PROP_KEYS)
            {
                values.Add((int)m_prop.GetPropertyNum(key, -1));
            }
            return values;
        }

        #endregion
    }

    /// <summary>
    /// 音楽室のコンポーネントプレイリスト
    /// </summary>
    public class PlayList : ComponentBase
    {
        #region 定数値

        //private static readonly string C_PROP_KEY_FONT = "Font";
        private static readonly string C_PROP_KEY_FONT_SIZE = "FontSize";
        private static readonly string C_PROP_KEY_FONT_COLOR = "FontColor";
        private static readonly string C_PROP_KEY_ITEM_HEIGHT = "LineHeight";
        private static readonly string C_PROP_KEY_SEL_BG_COLOR = "SelectedBG";

        #endregion

        #region メンバフィールド

        private ControlContext controlContext;
        private Properties m_prop;
        private ITexture m_upper;
        private ITexture m_bottom;
        private ITexture m_left;
        private ITexture m_right;
        private GUIListBox m_lstBox;	//!< リストボックス

        private int m_uy;	// リスト描画y
        private int m_by;	// リスト底描画位置
        private int m_rx;	// 右の描画位置
        private int m_lstHeight;

        private bool init;

        #endregion

        public PlayList(IMouseInput m_, ControlContext controlContext)
            : base(m_)
        {
            this.controlContext = controlContext;
        }

        /// 新規選択されたかどうか
        public bool IsNewSelected()
        {
            return m_lstBox.IsNewSelect();
        }

        /// 新規データのファイルパス
        public int GetSelectedNum()
        {
            return m_lstBox.GetSelectedNum();
        }

        /// 選択状態にする
        public void SetSelect(int num)
        {
            m_lstBox.SetSelect(num);
        }

        public override void OnMove(IScreen screen)
        {
            if (!init)
            {
                OnInit();
            }
            m_lstBox.OnMove(screen);
        }

        public override void OnDraw(IScreen screen)
        {
            // 枠描画
            screen.Blt(m_upper, m_dx, m_dy);

            // 左右描画
            int unitHeight = (int)m_left.Height;
            for (int y = this.m_uy; y < m_lstHeight; y += unitHeight)
            {
                screen.Blt(m_left, m_dx, y);
                screen.Blt(m_right, m_rx, y);
            }

            // 底描画
            screen.Blt(m_bottom, m_dx, m_by);

            m_lstBox.OnDraw(screen);
        }



        #region 非公開メンバ

        /// タイトルリストの読み込み
        private static string[] GetTitleList()
        {
            string str = YamalibUtility.ReadTextFile("img2/music/title.lst");
            return str.Split(new char[] { '\n' });
        }

        /// 初期化処理
        private void OnInit()
        {
            m_prop = Properties.GetInstance("img2/music/skin/basic/pl.txt");

            m_upper = YamalibConst.CreateTexture("img2/music/skin/basic/pl_upper.png");
            m_left = YamalibConst.CreateTexture("img2/music/skin/basic/pl_left.png");
            m_right = YamalibConst.CreateTexture("img2/music/skin/basic/pl_right.png");
            m_bottom = YamalibConst.CreateTexture("img2/music/skin/basic/pl_bottom.png");

            Properties propGen = GetGenProp();
            m_dx = (int)propGen.GetPropertyNum(C_PROP_KEY_PL_POSX, 0);
            m_dy = (int)propGen.GetPropertyNum(C_PROP_KEY_PL_POSY, 0);

            this.m_uy = m_dy + (int)m_upper.Height;
            CreateListBox();

            init = true;
        }

        /// リストボックスの生成
        private void CreateListBox()
        {
            //Log.print("PlayList#CreateListBox start!");

            m_lstBox = new GUIListBox();
            ITexture scrollBarTex = YamalibConst.CreateTexture("img2/music/skin/basic/bar2.png");
            TextureScrollbar scrollBar = new TextureScrollbar();
            scrollBar.OnInit(controlContext);
            scrollBar.BarTexture = scrollBarTex;
            m_lstBox.SetScrollbar(scrollBar);

            Properties propGen = GetGenProp();
            int sizex = (int)propGen.GetPropertyNum(C_PROP_KEY_PL_SZX, 0);
            int sizey = (int)propGen.GetPropertyNum(C_PROP_KEY_PL_SZY, 0);

            int offx = (int)m_left.Width;

            Rect rc = new Rect();
            rc.SetRect(m_dx + offx, m_dy + this.m_uy, m_dx + sizex, m_dy + sizey);
            m_lstBox.SetArea(rc);
            m_lstBox.SetXY(m_dx + offx, m_dy + this.m_uy);


            // 下地テクスチャの設定
            ITexture t = YamalibConst.CreateTexture("img2/music/skin/basic/pl_base.png");
            m_lstBox.SetBaseTexture(t);

            // リストのフォントサイズ
            float fontsz = (float)m_prop.GetPropertyDecimal(C_PROP_KEY_FONT_SIZE, 1.0);

            // フォントカラー
            string fontColor = m_prop.GetProperty(C_PROP_KEY_FONT_COLOR, "FFFFFF");
            Color4ub color = YanesdkUtil.ToColor4ub(fontColor);
            string strBgColor = m_prop.GetProperty(C_PROP_KEY_SEL_BG_COLOR, "000000");
            Color4ub bgColor = YanesdkUtil.ToColor4ub(strBgColor);

            // 位置項目のサイズ
            Size itemSz = new Size((int)t.Width, (int)m_prop.GetPropertyNum(C_PROP_KEY_ITEM_HEIGHT, 15));

            // アイテムを作る
            string[] titleNames = GetTitleList();
            int i = 0;
            foreach (string title in titleNames)
            {
                SimpleListBoxItem item = new SimpleListBoxItem(m_mouse);
                item.SetText(title);
                item.SetRate(fontsz);
                item.SetFontColor(color);
                item.SetSelBackColor(bgColor);

                if (0 == i)
                {
                    item.SetSelect(true);
                }

                // リストのサイズ指定
                item.SetSize(itemSz);
                m_lstBox.AddItem((ListBoxItem)item);
                ++i;
            }

            // スクロールバーの位置調整
            m_lstBox.GetScrollbar().SetXY(622, 30);
            m_lstBox.GetScrollbar().SetSize(10, sizey);


            // ここで右の描画位置を割り出しておく！！
            this.m_rx = m_dx + offx + (int)t.Width;
            this.m_lstHeight = (int)t.Height;
            this.m_by = this.m_uy + this.m_lstHeight;

            //Log.print("PlayList#CreateListBox IsFinish!");
        }


        #endregion
    }

    public class TitleParts : ComponentBase
    {
        #region メンバフィールド

        private bool init;
        private ITexture m_title;	//!< タイトル画像
        private ITexture m_old;

        #endregion

        public TitleParts(IMouseInput m_)
            : base(m_)
        {
        }

        /// テクスチャの設定
        public void SetTexture(ITexture t_)
        {
            this.m_old = this.m_title;
            m_title = t_;
        }

        /// タイトル画像を設定
        public void SetTitle(ITexture t_)
        {
            this.m_title = t_;
        }

        public override void OnMove(IScreen screen)
        {
            if (!init)
            {
                OnInit();
            }
        }

        public override void OnDraw(IScreen screen)
        {
            screen.Blt(m_main, m_dx, m_dy);

            // センタリグ描画
            int ttlx;
            int ttly;
            if (!(m_main == null) && !(m_title == null))
            {
                ttlx = m_dx + (int)((m_main.Width - m_title.Width) / 2);
                ttly = m_dy + (int)((m_main.Height - m_title.Height) / 2);
            }
            else
            {
                ttlx = m_dx;
                ttly = m_dy;
            }

            screen.Blt(m_title, ttlx, ttly);
        }

        #region 非公開メンバ

        /// 初期化処理
        void OnInit()
        {
            Properties propGen = GetGenProp();
            m_dx = (int)propGen.GetPropertyNum(C_PROP_KEY_TTL_POSX, 0);
            m_dy = (int)propGen.GetPropertyNum(C_PROP_KEY_TTL_POSY, 0);
            m_main = YamalibConst.CreateTexture("img2/music/skin/basic/title_base.png");

            init = true;
        }


        #endregion
    }

    public class Description : ComponentBase
    {
        #region 定数値

        private static readonly string C_PROP_KEY_OFFSETX = "text_offsetx";
        private static readonly string C_PROP_KEY_OFFSETY = "text_offsety";

        #endregion

        #region メンバフィールド

        private bool init;

        private ScenarioDrawContext scenarioDrawContext;
        private ScenarioParser scenarioParser;
        private readonly FontRepository mainTextFontRep = new FontRepository(YamalibConst.FONT_REP_TEXTURE_FACTORY);
        private readonly FontRepository rubiTextFontRep = new FontRepository(YamalibConst.FONT_REP_TEXTURE_FACTORY);

        private Properties m_prop;

        private readonly FontLoader m_fl;
        private readonly int textFontNo;
        private readonly int rubiFontNo;

        private bool m_drawShadow;
        private ITexture m_old;
        private ITexture m_bg;	// 背景画像
        private string[] m_filenames;

        private int m_ox;
        private int m_oy;

        private int m_areax;
        private int m_areay;

        #endregion

        public Description(IMouseInput m_, FontLoader fontLoader, int textFontNo, int rubiFontNo)
            : base(m_)
        {
            m_drawShadow = true;
            m_fl = fontLoader;
            this.textFontNo = textFontNo;
            this.rubiFontNo = rubiFontNo;
        }

        /// テクスチャの設定
        public void SetTexture(ITexture t_)
        {
            this.m_old = this.m_bg;
            this.m_bg = t_;
        }

        /// 説明番号の設定 
        public void SetDescNo(int no)
        {
            if (no < 0 || no >= m_filenames.Length) return;

            string strText = YamalibUtility.ReadTextFile(m_filenames[no]);
            scenarioDrawContext.SetText(strText);
            scenarioParser.SetScenarioDrawContext(scenarioDrawContext);
            scenarioParser.UpdateText();
        }

        /// 影を描画するか
        void DrawShadow(bool drawFlg)
        {
            m_drawShadow = drawFlg;
        }

        public override void OnMove(IScreen screen)
        {
            if (!init)
            {
                OnInit();
            }
        }

        public override void OnDraw(IScreen screen)
        {
            screen.Blt(m_main, m_dx, m_dy);
            // センタリグ描画
            int bgx;
            int bgy;
            if (!(m_main == null) && !(m_bg == null))
            {
                bgx = m_dx + (int)((m_main.Width - m_bg.Width) / 2);
                bgy = m_dy + (int)((m_main.Height - m_bg.Height) / 2);
                screen.Blt(m_bg, bgx, bgy);
            }

            // カラーバックアップ
            Color4ub colorOrg = YanesdkUtil.GetNowScreenColor(screen);
            screen.BlendSrcAlpha();
            scenarioParser.OnPaint(screen, m_dx + m_ox, m_dy + m_oy);
            screen.SetColor(colorOrg);
        }


        #region 非公開メンバ

        /// 初期化処理
        private void OnInit()
        {
            Properties propGen = GetGenProp();
            m_dx = (int)propGen.GetPropertyNum((string)C_PROP_KEY_DSC_POSX, 0);
            m_dy = (int)propGen.GetPropertyNum((string)C_PROP_KEY_DSC_POSY, 0);

            m_prop = Properties.GetInstance((string)"img2/music/skin/basic/desc.txt");
            m_ox = (int)m_prop.GetPropertyNum((string)C_PROP_KEY_OFFSETX, 5);
            m_oy = (int)m_prop.GetPropertyNum((string)C_PROP_KEY_OFFSETY, 5);

            m_main = YamalibConst.CreateTexture("img2/music/skin/basic/desc_base.png");

            m_areax = (int)m_main.Width;
            m_areay = (int)m_main.Height;

            ReadLst();
            InitTextDraw();

            init = true;
        }

        private void InitTextDraw()
        {
            mainTextFontRep.SetLoader(m_fl, textFontNo);
            mainTextFontRep.Max = 300;
            rubiTextFontRep.SetLoader(m_fl, rubiFontNo);
            rubiTextFontRep.Max = 300;

            scenarioDrawContext = new ScenarioDrawContext();
            scenarioDrawContext.SetText(YamalibUtility.ReadTextFile(m_filenames[0]));
            scenarioDrawContext.DrawWidth = m_areax - m_ox - 20;
            scenarioDrawContext.BlankHeight = -3;
            scenarioDrawContext.CharacterInterval = -1;
            scenarioDrawContext.TextColor = YanesdkUtil.BLOCK_COLOR;

            scenarioParser = new ScenarioParser();
            scenarioParser.TextFontRepository = mainTextFontRep;
            scenarioParser.RubiFontRepository = rubiTextFontRep;
            scenarioParser.SetScenarioDrawContext(scenarioDrawContext);

            scenarioParser.UpdateText();
        }

        private void ReadLst()
        {
            m_filenames = YamalibUtility.ReadTextFile("img2/music/desc/lst.txt").Split(new char[] { '\n' });
            for (int i = 0; i < m_filenames.Length; i++)
            {
                if (m_filenames[i] == "")
                {
                    continue;
                }
                m_filenames[i] = m_filenames[i].Substring(0, m_filenames[i].Length - 1);
            }
        }



        #endregion
    }
}
