#region Using ステートメント

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using MikuMikuDance.XNA.Debug.Utils;

#endregion

namespace MikuMikuDance.XNA.Debug
{
    /// <summary>
    /// キーボード入力関連のユーティリティクラス(伊藤 雄一(HN:ひげねこ)作)
    /// </summary>
    public abstract class KeyboardUtils
    {
        #region フィールド

        /// <summary>
        /// 通常の文字とシフトキーが押下された時の文字を保持する文字ペアクラス
        /// </summary>
        class CharPair
        {
            public CharPair( char normalChar, Nullable<char> shiftChar )
            {
                this.NormalChar = normalChar;
                this.ShiftChar = shiftChar;
            }

            public char NormalChar;
            public Nullable<char> ShiftChar;
        }

        // キー:Keys, 値:CharPair
        private Dictionary<Keys, CharPair> keyMap =
                                                    new Dictionary<Keys, CharPair>();

        #endregion

        /// <summary>
        /// キー情報から文字を取得する
        /// </summary>
        /// <param name="key">押下されたキー</param>
        /// <param name="shitKeyPressed">シフトキーが押されていたか?</param>
        /// <param name="character">キー入力から変換された文字</param>
        /// <returns>文字取得が成功した場合trueを返す</returns>
        public bool KeyToString( Keys key, bool shitKeyPressed,
                                                                    out char character )
        {
            bool result = false;
            character = ' ';
            CharPair charPair;

            if ( ( Keys.A <= key && key <= Keys.Z ) || key == Keys.Space )
            {
                // A〜Z、スペースキーはそのまま文字コードとして使用する
                character = ( shitKeyPressed ) ? (char)key : Char.ToLower( (char)key );
                result = true;
            }
            else if ( keyMap.TryGetValue( key, out charPair ) )
            {
                // それ以外の場合はKeyMapの情報を元に変換する
                if ( !shitKeyPressed )
                {
                    character = charPair.NormalChar;
                    result = true;
                }
                else if ( charPair.ShiftChar.HasValue )
                {
                    character = charPair.ShiftChar.Value;
                    result = true;
                }
            }

            return result;
        }

        #region 初期化
        /// <summary>
        /// キーボードutilの初期化
        /// </summary>
        public KeyboardUtils()
        {
            InitializeKeyMap();
        }

        /// <summary>
        /// 英字以外のキーの文字マップの初期化
        /// </summary>
        /// <remarks>継承先でレイアウトを設定</remarks>
        protected abstract void InitializeKeyMap();
        

        /// <summary>
        ///　キーボードのキーと文字マップの追加
        /// </summary>
        /// <param name="key">キーボードのキー</param>
        /// <param name="charPair">
        /// 文字、２文字の場合はシフトキー無し、有り順番に記述する</param>
        protected void AddKeyMap( Keys key, string charPair )
        {
            char char1 = charPair[0];
            Nullable<char> char2 = null;
            if ( charPair.Length > 1 )
                char2 = charPair[1];

            keyMap.Add( key, new CharPair( char1, char2 ) );
        }

        #endregion

        /// <summary>
        /// ファクトリーメソッド
        /// </summary>
        /// <param name="type">キーボードタイプ</param>
        /// <returns>KeyboardUtils</returns>
        public static KeyboardUtils Create(KeyboardType type)
        {
            switch (type)
            {
                case KeyboardType.Japanese:
                    return new JapaneseKeyboardUtils();
                case KeyboardType.English:
                    return new EnglishKeyboardUtil();
                default:
                    throw new NotImplementedException();
            }
        }
    }

}
