using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Kyojin.Model
{

    /// <summary>
    /// セーブデータをまとめてシリアライズするためのコンテナ
    /// </summary>
    [Serializable]
    public class SaveDataContainer
    {
        #region メンバフィールド

        private UserInfo userInfo;
        private OptionInfo optionInfo;
        private KeyConfigData keyConfigData;

        #endregion

        public UserInfo UserInfo
        {
            get { return userInfo; }
            set { userInfo = value; }
        }

        public OptionInfo OptionInfo
        {
            get { return optionInfo; }
            set { optionInfo = value; }
        }

        public KeyConfigData KeyConfigData
        {
            get { return keyConfigData; }
            set { keyConfigData = value; }
        }

    }


    /// <summary>
    /// ユーザ情報
    /// </summary>
    [Serializable]
    public class UserInfo
    {
        private readonly List<bool> readFlags = new List<bool>();
        private readonly List<long> readPos = new List<long>();
        private readonly List<BookmarkData> bookmarkData = new List<BookmarkData>();

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public UserInfo()
        {
            int scenarioMax = (int)KyojinConst.ScenarioID.STORY2ch01;
            readFlags.Capacity = readPos.Capacity = scenarioMax;

            // 念のため初期化
            for (int i = 0; i < readFlags.Capacity; i++)
            {
                readFlags.Add(false);
                readPos.Add(0);
            }
        }


        /// <summary>
        /// 既読位置を取得する
        /// </summary>
        /// <param name="scenarioId"></param>
        /// <param name="pos"></param>
        public void SetReadPos(KyojinConst.ScenarioID scenarioId, long pos)
        {
            int index = (int)scenarioId;
            if (index >= readPos.Count || GetReadPos(scenarioId) >= pos)
            {
                return;
            }
            readPos[index] = pos;
        }

        public long GetReadPos(KyojinConst.ScenarioID scenarioId)
        {
            Debug.Assert((int)scenarioId < readPos.Count);
            return readPos[(int)scenarioId];
        }

        /// <summary>
        /// 既読フラグを設定する
        /// </summary>
        /// <param name="scenarioNo"></param>
        /// <param name="flg"></param>
        public void SetReadFlg(int scenarioNo, bool flg)
        {
            readFlags[scenarioNo] = flg;
        }

        /// <summary>
        ///  既読かどうか
        /// </summary>
        /// <param name="scenarioNo"></param>
        /// <returns></returns>
        public bool IsRead(int scenarioNo)
        {
            return readFlags[scenarioNo];
        }

        /// <summary>
        /// 全フラグの取得
        /// </summary>
        public List<bool> ReadFlgs
        {
            get { return readFlags; }
        }

        /// <summary>
        /// ブックマークデータを取得する
        /// </summary>
        public List<BookmarkData> BookmarkData
        {
            get { return bookmarkData; }
        }

        /// <summary>
        /// メインパートをすべて呼んだか？
        /// </summary>
        /// <returns></returns>
        public bool IsReadMainPart()
        {
            for (int i = 0; i < (int)KyojinConst.ScenarioID.STORY07; i++)
            {
                if (!readFlags[i])
                {
                    return false;
                }
            }
            return true;
        }

        /// 去人パートを読み終えたか
        public bool IsReadKyojin()
        {
            for (int i = (int)KyojinConst.ScenarioID.KYOJIN01; i < (int)KyojinConst.ScenarioID.KYOJIN03; ++i)
            {
                if (!readFlags[i])
                {
                    return false;
                }
            }

            return true;
        }
    }

    /// <summary>
    /// オプション設定情報を保持
    /// </summary>
    [Serializable]
    public class OptionInfo
    {
        public enum TEXT_SPEED { NORMAL = 1, FAST = 2, LINE, PAGE };

        private bool bgmOn = true;
        private bool seOn = true;
        private bool voiceOn = false;
        private bool windowMode = true;

        private int textSpeed = (int)TEXT_SPEED.NORMAL;
        private int bgmVol = 80;
        private int seVol = 80;
        private int voiceVol = 100;

        public bool WindowMode
        {
            get { return windowMode; }
            set { windowMode = value; }
        }


        public int BGMVolume
        {
            set { bgmVol = Roundvol(value); }
            get { return bgmVol; }
        }

        public int SEVolume
        {
            set { seVol = Roundvol(value); }
            get { return seVol; }
        }

        public int VoiceVolume
        {
            set { voiceVol = Roundvol(value); }
            get { return voiceVol; }
        }

        public bool BGMOn
        {
            set { bgmOn = value; }
            get { return bgmOn; }
        }

        public bool SEOn
        {
            get { return seOn; }
            set { seOn = value; }
        }

        public bool VoiceOn
        {
            get { return voiceOn; }
            set { voiceOn = value; }
        }
        public int TextSpeed
        {
            set { textSpeed = value; }
            get { return textSpeed; }
        }

        private int Roundvol(int volume)
        {
            if (100 < volume) return 100;
            else if (0 > volume) return 0;
            return volume;
        }
    }

    /// <summary>
    /// キーコンフィグデータを保持
    /// </summary>
    [Serializable]
    public class KeyConfigData
    {
        public const int KEY_CONFIG_MAX = 64;	//!< これ以上のキー割り当てしようなんて...
        private readonly List<int[]> m_keyData = new List<int[]>();
        private string m_deviceName;	//!< このKEYの対象となった入力装置の名前

        public KeyConfigData()
        {
            for (int i = 0; i < KEY_CONFIG_MAX; i++)
            {
                m_keyData.Add(null);
            }
        }

        public void SetKeyData(int id, int[] keyNo)
        {
            m_keyData[id] = keyNo;
        }
        
        public List<int[]> KeyData
        {
            get { return m_keyData; }
        }

        public string DeviceName
        {
            get { return m_deviceName; }
            set { m_deviceName = value; }
        }
    }

}
