using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

namespace NetVision {
    public partial class Player : System.Windows.Forms.Panel {

        #region フィールド

        /// <summary>
        /// プレイヤー名
        /// </summary>
        public string PlayerName { get; set; }

        /// <summary>
        /// プレイヤーの状態
        /// </summary>
        public PlayerState State { get; set; }

        /// <summary>
        /// プレイヤーのタイプ
        /// </summary>
        public PlayerType Type { get; set; }

        /// <summary>
        /// 相手プレイヤー
        /// </summary>
        public Player Enemy { get; set; }

        /// <summary>
        /// 全てのカードリスト
        /// </summary>
        public CardList AllList { get; set; }

        /// <summary>
        /// 裏向きカードのリスト
        /// </summary>
        public CardList BackList { get; set; }


        /// <summary>
        /// 画面上側か
        /// </summary>
        public bool IsUpSide { get; set; }

        /// <summary>
        /// デッキレシピ
        /// </summary>
        public Dictionary<string, int> DeckRecipe { get; private set; }

        /// <summary>
        /// サイドボードのレシピ
        /// </summary>
        public Dictionary<string, int> SideRecipe { get; private set; }

        /// <summary>
        /// デッキ内のカード全部
        /// </summary>
        public Dictionary<int, CardBox> CardTable { get; private set; }

        /// <summary>
        /// コマンドが送られるときのイベント
        /// </summary>
        public event EventHandler<MessageEventArgs> CommandSending;
        protected void OnCommandSending( object sender, MessageEventArgs e ) {
            if (CommandSending != null) { CommandSending(this, e); }
        }

        /// <summary>
        /// ログメッセージを表示する必要があるとき
        /// </summary>
        public event EventHandler<LogMessageArgs> LogMessage;
        public void OnLogMessage( object sender, LogMessageArgs e ) {
            if (LogMessage != null) { LogMessage(this, e); }
        }

        #endregion


        #region クリック処理

        /// <summary>
        /// 最終クリック時間
        /// </summary>
        public DateTime ClickTime{ get; set; }

        /// <summary>
        /// 最終クリックカード
        /// </summary>
        public CardBox ClickCard = null;

        #endregion

        #region フォームコントロール

        /// <summary>
        /// 場コントロール
        /// </summary>
        [Category("コントロール")]
        public FieldControl BattleField { get; set; }

        /// <summary>
        /// デッキコントロール
        /// </summary>
        [Category("コントロール")]
        public DeckControl Deck { get; set; }

        /// <summary>
        /// 手札コントロール
        /// </summary>
        [Category("コントロール")]
        public HandControl Hands { get; set; }

        /// <summary>
        /// 冥界コントロール
        /// </summary>
        [Category("コントロール")]
        public GraveControl Grave { get; set; }

        /// <summary>
        /// ノードコントロール
        /// </summary>
        [Category("コントロール")]
        public NodeControl Nodes { get; set; }

        /// <summary>
        /// 除外コントロールコントロール
        /// </summary>
        [Category("コントロール")]
        public SideControl Removes { get; set; }

        /// <summary>
        /// サイドボードコントロール
        /// </summary>
        [Category("コントロール")]
        public SideControl Sidebord { get; set; }

        /// <summary>
        /// カード情報コントロール
        /// </summary>
        [Category("コントロール")]
        public CardInfoControl CardInfo { get; set; }

        /// <summary>
        /// カーソル
        /// </summary>
        [Category("コントロール")]
        public Cursor CardCursor { get; set; }

        /// <summary>
        /// カードリストビュー
        /// </summary>
        [Category("コントロール")]
        public CardListView CardListViews { get; set; }

        /// <summary>
        /// ライフコントロール
        /// </summary>
        [Category("コントロール")]
        public LifeManager Life { get; set; }

        /// <summary>
        /// スタートボタン
        /// </summary>
        [Category("コントロール")]
        public Button StartButton { get; set; }

        /// <summary>
        /// 召喚チェック
        /// </summary>
        [Category("コントロール")]
        public CheckBox SummonChar { get; set; }

        /// <summary>
        /// 人形チェック
        /// </summary>
        [Category("コントロール")]
        public CheckBox SummonDoll { get; set; }

        /// <summary>
        /// ノードセットチェック
        /// </summary>
        [Category("コントロール")]
        public CheckBox NodeSet { get; set; }

        /// <summary>
        /// エリアの一覧
        /// </summary>
        public Dictionary<AreaType, AreaControl> Areas;

        #endregion


        #region 初期処理



        /// <summary>
        /// デッキレシピをロード
        /// </summary>
        /// <param name="filename">デッキファイル名</param>
        public void LoadRecipe(string filename){
            DeckRecipe = new Dictionary<string, int>();
            SideRecipe = new Dictionary<string, int>();
            using (StreamReader fs = new StreamReader(filename, Encoding.GetEncoding("Shift_JIS"))) {
                Regex reg = new Regex(@"^(\d),(\w+),");
                Regex splitter = new Regex(@"^--$");
                bool on_side = false;
                while (!fs.EndOfStream) {
                    string line = fs.ReadLine();
                    if (splitter.IsMatch(line)) { on_side = true; continue; }
                    if (reg.IsMatch(line)) {
                        Match m = reg.Match(line);
                        string id = m.Groups[2].Value;
                        if (!AllList.Items.ContainsKey(id)) { throw new Exception("存在しないカードが指定されました。"); }
                        int num = int.Parse(m.Groups[1].Value);
                        if (!on_side) { DeckRecipe[id] = num; } else { SideRecipe[id] = num; }
                    }
                }
            }
        }
        /// <summary>
        /// 山札をセットアップ
        /// </summary>
        /// <param name="?"></param>
        public void SetupDeck(){

            // コントロールの初期化
            Life.Touchable = Type == PlayerType.Control;
            Life.Value = 25;


            CardTable = new Dictionary<int, CardBox>();

            // 山札をセットアップ
            foreach (KeyValuePair<string, int> rep in DeckRecipe) {
                for (int i = 0; i < rep.Value; i++) {
                    CardInfo card = AllList[rep.Key];
                    CardBox box = CreateCardBox(card);
                    box.Id = Deck.Count + 1;
                    box.Area = AreaType.Deck;
                    CardTable[box.Id] = box;
                    Deck.Add(box);
                }
            }
            // サイドボード
            foreach (KeyValuePair<string, int> rep in SideRecipe) {
                for (int i = 0; i < rep.Value; i++) {
                    CardInfo card = AllList[rep.Key];
                    CardBox box = CreateCardBox(card);
                    box.Id = Deck.Count + Sidebord.Count + 1;
                    box.Area = AreaType.SideBord;
                    CardTable[box.Id] = box;
                    Sidebord.Add(box);
                }
            }
            //            Deck.Shuffle();
        }

        /// <summary>
        /// カードコントロールの生成と初期化
        /// </summary>
        /// <param name="info">元となるカード情報</param>
        /// <returns>作成されたCardBox</returns>
        private CardBox CreateCardBox(CardInfo info) {

            CardBox box = new CardBox();

            // 基本プロパティ
            box.Info = info;
            box.Player = this;
            box.Owner = this;
            box.Visible = false;

            return box;
        }


        #endregion

        /// <summary>
        /// すべての情報をクリア
        /// </summary>
        public void Clear() {
            if (State == PlayerState.UnLoad) { return; }
            if (DeckRecipe != null) { DeckRecipe.Clear(); }
            if (SideRecipe != null) { SideRecipe.Clear(); }
            ClickCard = null;
            foreach (AreaControl area in Areas.Values) {
                area.Clear();
            }
            foreach (CardBox card in CardTable.Values) {
                card.Clear();
            }
            CardTable.Clear();

            State = PlayerState.UnLoad;
            Type = PlayerType.Undef;
        }

        /// <summary>
        /// ウィンドウサイズをリサイズしたときの処理
        /// </summary>
        public void OnResize() {
            if (State == PlayerState.UnLoad) { return; }
            BattleField.RedrawCards();
            Hands.RedrawCards();
        }

        #region シャドウ

        /// <summary>
        /// シリアライズ用のシャドウを作成
        /// </summary>
        /// <returns>シャドウ</returns>
        public PlayerShadow GetShadow() {
            PlayerShadow shadow = new PlayerShadow();
            shadow.Cards = new Dictionary<AreaType, List<CardShadow>>();
            foreach (AreaControl area in Areas.Values) {
                shadow.Cards[area.Type] = new List<CardShadow>();
                foreach (CardBox card in area.Cards) {
                    CardShadow cs = new CardShadow();
                    cs.Id = card.Id;
                    cs.No = card.Info.No;
                    cs.Active = card.Active;
                    cs.FaceSide = card.FaceSide;
                    cs.Transformed = card.Transformed;
                    cs.Location = card.VirtualPoint;
                    if (card.BackCardInfo.No != null && card.BackCardInfo.No != "000") cs.BackInfo = card.BackCardInfo.No;
                    shadow.Cards[area.Type].Insert(0, cs);
                }
            }
            shadow.Life = Life.Value;
            shadow.State = State;
            shadow.PlayerName = PlayerName;
            return shadow;
        }

        /// <summary>
        /// シャドウから復元
        /// </summary>
        /// <param name="shadow">シャドウ</param>
        public void LoadFromShadow(PlayerShadow shadow) {
            Clear();
            State = shadow.State;
            Life.Value = shadow.Life;
            PlayerName = shadow.PlayerName;
            CardTable = new Dictionary<int, CardBox>();
            foreach (KeyValuePair<AreaType, List<CardShadow>> val in shadow.Cards) {
                AreaControl area = Areas[val.Key];
                if (val.Value == null) { continue; }
                foreach(CardShadow cs in val.Value){
                    CardBox card = CreateCardBox(AllList[cs.No]);
                    card.Id = cs.Id;
                    card.Area = area.Type;
                    card.FaceSide = cs.FaceSide;
                    card.Active = cs.Active;
                    card.Transformed = cs.Transformed;
                    card.BorderStyle = BorderStyle.FixedSingle;
                    card.BackCardInfo = (cs.BackInfo != null) ? BackList[cs.BackInfo] : BackList["000"];
                    CardTable[card.Id] = card;
                    area.Add(card);
                    if (card.Area == AreaType.Field || card.Area == AreaType.Nodes) { card.MoveVirtualPoint(cs.Location); }
                    card.Visible = (area.Type != AreaType.Removed) && (area.Type != AreaType.SideBord);
                }
            }
        }

        #endregion

    }

}
