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


namespace NetVision {

    public partial class CardBox : UserControl {

        #region コンテキストメニュー関係


        /// <summary>
        /// コンテキストメニュー開くとき
        /// </summary>
        private void contextMenuCard_Opening( object sender, CancelEventArgs e ) {
            if (Player.Type != PlayerType.Control) { e.Cancel = true; }
            if (Area == AreaType.Field) {

                行動ToolStripMenuItem.Visible = true;

                裏向きToolStripMenuItem.Visible = true;
                裏向きToolStripMenuItem.Checked = !FaceSide;

                if (Info.PlayingType == PlayingType.Character || Info.PlayingType == PlayingType.Phantasmal || !FaceSide) {
                    変身ToolStripMenuItem.Visible = true;
                    変身ToolStripMenuItem.Checked = Transformed;
                }
                else { 変身ToolStripMenuItem.Visible = false; }

                スリープToolStripMenuItem.Visible = true;
                スリープToolStripMenuItem.Checked = !Active;

                マナチャージToolStripMenuItem.Visible = Active && ( Player.Deck.Count > 0 );
                起動効果SToolStripMenuItem.Visible = Active;

                防御ToolStripMenuItem.Visible = Active && ( Player.State == PlayerState.YourTurn );
                攻撃ToolStripMenuItem.Visible = Active && ( Player.State == PlayerState.MyTurn );
                表示順序ToolStripMenuItem.Visible = true;

                if (!FaceSide) {
                    裏向きカードの定義ToolStripMenuItem.Visible = true;
                    裏向きカードの定義ToolStripMenuItem.DropDownItems.Clear();
                    CardList backs = Player.BackList;
                    List<CardInfo> nomi = new List<CardInfo>();
                    nomi.Add(backs["000"]);

                    foreach (CardBox card in Player.BattleField.Cards) {
                        if (backs.Items.ContainsKey(card.Info.No) && !nomi.Contains(backs[card.Info.No])) { nomi.Add(backs[card.Info.No]); }
                    }
                    foreach (CardBox card in Player.Enemy.BattleField.Cards) {
                        if (backs.Items.ContainsKey(card.Info.No) && !nomi.Contains(backs[card.Info.No])) { nomi.Add(backs[card.Info.No]); }
                    }
                    foreach (CardBox card in Player.Grave.Cards) {
                        if (backs.Items.ContainsKey(card.Info.No) && !nomi.Contains(backs[card.Info.No])) { nomi.Add(backs[card.Info.No]); }
                    }
                    foreach (CardInfo info in nomi) {
                        ToolStripMenuItem menu = (ToolStripMenuItem)裏向きカードの定義ToolStripMenuItem.DropDownItems.Add(info.Name + "(" + info.User + ")");
                        menu.Tag = info.No;
                        menu.Click += new EventHandler(裏定義_Click);
                        menu.Checked = BackCardInfo.No == info.No;
                    }
                }
                else { 裏向きカードの定義ToolStripMenuItem.Visible = false; }

            }
            else {
                行動ToolStripMenuItem.Visible = false;
                裏向きToolStripMenuItem.Visible = false;
                スリープToolStripMenuItem.Visible = false;
                変身ToolStripMenuItem.Visible = false;
                裏向きカードの定義ToolStripMenuItem.Visible = false;
                表示順序ToolStripMenuItem.Visible = false;
            }
            if (Area == AreaType.Nodes) {
                スリープToolStripMenuItem.Visible = true;
                スリープToolStripMenuItem.Checked = !Active;
                表示順序ToolStripMenuItem.Visible = true;
            }

            コストの支払いToolStripMenuItem.Visible = ( Area == AreaType.Nodes );
            公開するToolStripMenuItem.Visible = ( Area == AreaType.Deck || Area == AreaType.Hands );
            上からX枚見るToolStripMenuItem.Visible = ( Area == AreaType.Deck );
            全て見るToolStripMenuItem.Visible = ( Area == AreaType.Deck || Area == AreaType.Grave || Area == AreaType.SideBord || Area == AreaType.Removed );
            プレイToolStripMenuItem.Visible = Area == AreaType.Hands;
            シャッフルToolStripMenuItem.Visible = ( Area == AreaType.Deck );

        }




        /// <summary>
        /// 移動メニューをクリック
        /// </summary>
        private void ToolStripMenuItemJumps_Click( object sender, EventArgs e ) {
            string title = ( (ToolStripItem)sender ).Text;
            Command com = new Command { Type = CommandType.Jump, Card = this };
            switch (title) {
                case "場":
                    com.ToArea = AreaType.Field;
                    com.Active = true;
                    com.FaceSide = true;
                    break;
                case "場[S]":
                    com.ToArea = AreaType.Field;
                    com.Active = false;
                    com.FaceSide = true;
                    break;
                case "場[裏向き]":
                    com.ToArea = AreaType.Field;
                    com.Active = true;
                    com.FaceSide = false;
                    break;
                case "場[裏向き,S]":
                    com.ToArea = AreaType.Field;
                    com.Active = false;
                    com.FaceSide = false;
                    break;
                case "ノード":
                    com.ToArea = AreaType.Nodes;
                    com.Active = true;
                    com.Location = Player.Nodes.GetEmptyLocation(this);
                    break;
                case "ノード[S]":
                    com.ToArea = AreaType.Nodes;
                    com.Active = false;
                    com.Location = Player.Nodes.GetEmptyLocation(this);
                    break;
                case "手札":
                    com.ToArea = AreaType.Hands;
                    break;
                case "山札":
                    com.ToArea = AreaType.Deck;
                    break;
                case "山札の下":
                    com.ToArea = AreaType.UnderDeck;
                    break;
                case "冥界":
                    com.ToArea = AreaType.Grave;
                    break;
                case "除外":
                    com.ToArea = AreaType.Removed;
                    break;
                case "サイドボード":
                    com.ToArea = AreaType.SideBord;
                    break;
                default:
                    com.Type = CommandType.Undef;
                    break;
            }
            Player.SendCommand(com);
        }


        private void アクティブToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Change, Card = this, Active = !Active, FaceSide = FaceSide, Transformed = Transformed });
            スリープToolStripMenuItem.Checked = Active;
        }

        private void 裏向きToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Change, Card = this, Active = Active, FaceSide = !FaceSide, Transformed = Transformed });
            裏向きToolStripMenuItem.Checked = FaceSide;
        }
        private void 変身ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Change, Card = this, Active = Active, FaceSide = FaceSide, Transformed = !Transformed });
            変身ToolStripMenuItem.Checked = Transformed;
        }
        private void 攻撃ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Attack, Card = this });
        }
        private void 防御ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Defend, Card = this });
        }

        private void マナチャージToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.ManaCharge, Card = this });
        }
        private void コストの支払いToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.PayCost, Active = Active, Card = this });
        }
        private void 全て見るToolStripMenuItem_Click( object sender, EventArgs e ) {
            if (Area == AreaType.Deck) {
                DialogResult rs = MessageBox.Show("山札全てを見ますか？", "山札を開く", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (rs != DialogResult.Yes) { return; }
            }
            Player.CardListViews.ShowCards(Player.Areas[Area]);
            Player.CardListViews.BringToFront();
            if (Area == AreaType.Deck) {
                Player.SendCommand(new Command { Type = CommandType.ViewDeck });
            }
        }
        private void 上からX枚見るToolStripMenuItem1_Click( object sender, EventArgs e ) {
            int num = getContextNum();
            Player.SendCommand(new Command { Type = CommandType.ViewDeck, Value = num });
            Player.CardListViews.ShowCards(Player.Deck, num);
            contextMenuCard.Hide();
        }
        private void x枚ドローToolStripMenuItem_Click( object sender, EventArgs e ) {
            int num = getContextNum();
            AreaType area = (AreaType)( (ToolStripMenuItem)sender ).Tag;
            bool face = ( area == AreaType.Field ) && ( (ToolStripMenuItem)sender ).Text.Contains("表向き");
            Player.SendCommand(new Command { Type = CommandType.Draw, Cards = Player.Deck.Cards.GetRange(0, num), Value = num, ToArea = area, FaceSide = face, Active = !(area == AreaType.Nodes || (area == AreaType.Field && !face)) });
        }
        private int getContextNum() {
            int num = 0;
            if (!Int32.TryParse(toolStripComboBoxDeckNum.Text.Substring(0, toolStripComboBoxDeckNum.Text.Length - 1), out num)) {
                num = Player.Deck.Count;
            }
            return num;
        }

        private void 裏定義_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.BackNameDefine, Card = this, Message = ( (ToolStripMenuItem)sender ).Tag.ToString() });
        }

        private void 起動効果ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.StartEffect, Card = this, Active = ( (ToolStripMenuItem)sender ).Text.Contains("[S]") });
        }
        private void 自動効果ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.AutoEffect, Card = this });
        }
        private void 最前面へToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.LayerChange, Card = this, Active = true });
        }
        private void 最背面へToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.LayerChange, Card = this, Active = false });
        }
        private void 相手の場ToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.MoveToEnemy, ToArea = (AreaType)((ToolStripMenuItem)sender).Tag, Card = this, Location = VirtualPoint });
        }
        private void プレイToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Type = CommandType.Play, ToArea = AreaType.Field, Card = this });
        }
        private void シャッフルToolStripMenuItem_Click( object sender, EventArgs e ) {
            if (Player.Type == PlayerType.Network) { Player.Enemy.SendCommand(new Command { Type = CommandType.ShuffleEnemy }); }
            else { Player.SendCommand(new Command { Type = CommandType.Shuffle }); }
        }
        private void 公開するToolStripMenuItem_Click( object sender, EventArgs e ) {
            Player.SendCommand(new Command { Card = this, Type = CommandType.Change, Active = true, FaceSide = ((ToolStripMenuItem)sender).Checked });
        }
        #endregion

        /// <summary>
        /// コマンドを作成
        /// </summary>
        /// <returns>作成されたコマンドオブジェクト</returns>
        public Command Command() {
            return new Command { Type = CommandType.Undef, Card = this, Active = Active, FaceSide = FaceSide, Transformed = Transformed };
        }


        /// <summary>
        /// リソースの解放
        /// </summary>
        public void Clear() {
            m_card = new CardInfo();
            Id = 0;
            if (CardImage != null && IsImageExist) { CardImage.Dispose(); Array.Clear(imgCache, 0, imgCache.Length); }
            Dispose();
        }

        #region イベント

        /// <summary>
        /// マウスが触れる
        /// </summary>
        private void CardBox_MouseEnter( object sender, EventArgs e ) {
            // カード情報を表示
            if (FaceSide || Player.Type == PlayerType.Control && Area == AreaType.Hands) {
                Player.CardInfo.ShowInfo(Info);
            }
            else if (Area == AreaType.Field) {
                Player.CardInfo.ShowInfo(BackCardInfo);
            }
            Player.CardHovering(this);

            // ツールチップ関連
            if (Properties.Settings.Default.UseToolTip) {
                if (!FaceSide && Area != AreaType.Field && !(Area == AreaType.Hands && Player.Type == PlayerType.Control)) { return; }
                toolTipCard.ToolTipTitle = ( FaceSide || Area == AreaType.Hands && Player.Type == PlayerType.Control ) ? Info.Name : BackCardInfo.Name;
                string text = FaceSide || ( Area == AreaType.Hands && Player.Type == PlayerType.Control ) ? Info.GetBreakedText(20) : BackCardInfo.GetBreakedText(20);
                if (text == "") { text = " "; }
                if (!Properties.Settings.Default.BaloonTip) {
                    toolTipCard.IsBalloon = false;
                    toolTipCard.Show(text, this.labelCover, new Point(this.Width, 0));

                }
                else {
                    toolTipCard.IsBalloon = Properties.Settings.Default.BaloonTip;
                                    if (Properties.Settings.Default.FadeToolTip) {
                                        toolTipCard.UseAnimation = true;
                                        toolTipCard.UseFading = true;
                                        toolTipCard.AutomaticDelay = 500;
                                    }
                                    else {
                                        toolTipCard.UseAnimation = false;
                                        toolTipCard.UseFading = false;
                                        toolTipCard.AutomaticDelay = 250;
                                    }
                    
                    toolTipCard.SetToolTip(this.pictureBox, text);
                    toolTipCard.SetToolTip(this.labelCover, text);
                    toolTipCard.SetToolTip(this.labelName, text);
                    toolTipCard.SetToolTip(this.labelSkill, text);
                    toolTipCard.SetToolTip(this.labelGraze, text);
                    toolTipCard.SetToolTip(this.labelStatus, text);
                }
            }
        }

        /// <summary>
        /// マウスが離れる
        /// </summary>
        private void CardBox_MouseLeave( object sender, EventArgs e ) {
            Player.CardInfo.HideInfo();
            Player.CardHovering(null);
            toolTipCard.Hide(this.labelCover);
//            toolTipCard.Hide(this.labelName);
//            toolTipCard.RemoveAll();
        }


        /// <summary>
        /// マウス移動
        /// </summary>
        private void CardBox_MouseMove( object sender, MouseEventArgs e ) {
            if (e.Button != MouseButtons.Left) { return; }
            Player.ClickTime.AddMinutes(-1);
            if (Player.Type != PlayerType.Control) { return; }
            Cursor cursor = Player.CardCursor;
            cursor.Location = cursor.Parent.PointToClient(PointToScreen(new Point(e.X - cursor.BaseLocation.X, e.Y - cursor.BaseLocation.Y)));

            // エリアコントロールとの当たり判定
            foreach (AreaControl area in Player.Areas.Values) {
                if (cursor.Area == area.Type && cursor.Player == Player) { continue; }
                area.IsFocus = false;
            }
            foreach (AreaControl area in Player.Enemy.Areas.Values) {
                if (cursor.Area == area.Type && cursor.Player == Player.Enemy) { continue; }
                area.IsFocus = false;
            }
            cursor.Player = Player;
            cursor.Area = Area;
            foreach (AreaControl area in Player.Areas.Values) {
                if (( new Rectangle(area.PointToScreen(new Point(0, 0)), area.Size) ).IntersectsWith(new Rectangle(cursor.PointToScreen(new Point(0, 0)), new Size( cursor.Size.Width / 2, cursor.Size.Height / 2 )))
                    && Area != area.Type) {
                    area.IsFocus = true;
                    cursor.Area = area.Type;
                    cursor.Player = Player;
                    return;
                }
            }
            foreach (AreaControl area in Player.Enemy.Areas.Values) {
                if (( new Rectangle(area.PointToScreen(new Point(0, 0)), area.Size) ).IntersectsWith(new Rectangle(cursor.PointToScreen(new Point(0, 0)), new Size( cursor.Size.Width / 2, cursor.Size.Height / 2 )))
                ){
                    area.IsFocus = true;
                    cursor.Area = area.Type;
                    cursor.Player = Player.Enemy;
                    return;
                }

            }
        }

        /// <summary>
        /// クリック
        /// </summary>
        private void CardBox_MouseClick( object sender, MouseEventArgs e ) {
            if (e.Button == MouseButtons.Middle) {
                Player.ExecWheelClick(this);
            }
        }

        /// <summary>
        /// マウスダウン
        /// </summary>
        public void CardBox_MouseDown( object sender, MouseEventArgs e ) {
            if (e.Button != MouseButtons.Left) { return; }
            if (Player.Type != PlayerType.Control) { return; }
            Player.OnLogMessage(this, new LogMessageArgs("") { Sound = "move.wav" });
            Player.CardCursor.Area = this.Area;
            Player.CardCursor.BaseLocation = new Point(e.X, e.Y);
            Player.CardCursor.CaptureCard(this); // カーソルでキャプチャ
        }


        /// <summary>
        /// マウスアップ
        /// </summary>
        public void CardBox_MouseUp( object sender, MouseEventArgs e ) {
            if (e.Button != MouseButtons.Left) { return; }
            CardBox card = this;
            Cursor cursor = Player.CardCursor;
            if (Player.Type != PlayerType.Control) { return; }
            cursor.Visible = false;
            foreach (AreaControl area in Player.Areas.Values) {
                area.IsFocus = false;
            }
            // 敵地へ移動
            if (cursor.Player == Player.Enemy) {
                if (MessageBox.Show("敵の場に移動してもよろしいですか？", "コントロール権の移動", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; }
                AreaControl area = Player.Enemy.Areas[cursor.Area];
                Point loc = area.PointToClient(cursor.ScreenRect.Location);
                loc.Y = area.Height - loc.Y - cursor.Height;
                Player.SendCommand(new Command { Type = CommandType.MoveToEnemy, ToArea = cursor.Area, Card = this,
                    Location = GetVirtualPoint(loc, area.Size) });
                area.IsFocus = false;
                return;
            }

            // その場の移動
            if (cursor.Area == Area) {
                if (Area == AreaType.Field || Area == AreaType.Nodes) {
                    Point xy = Parent.PointToClient(cursor.ScreenRect.Location);
                    if (Math.Abs(Location.X - xy.X) > 3 || Math.Abs(Location.Y - xy.Y) > 3) {
                        PointF vxy = GetVirtualPoint(xy, Parent.Size);
                        Player.SendCommand(new Command { Type = CommandType.Move, Card = card, Location = vxy });
                        Player.ClickTime.AddMinutes(-1);
                        return;
                    }
                }
                if (Area == AreaType.Hands) {
                    Point xy = Player.Hands.PointToClient(cursor.ScreenRect.Location);
                    for (int i=0; i< Player.Hands.Cards.Count; i++) {
                        if (Player.Hands.Cards[i].Left > xy.X - Size.Width / 2) {
                            if (Player.Hands.Cards[i] != this) {
                                Player.SendCommand(new Command { Type = CommandType.Move, Card = card, Value = i });
                                return;
                            }
                            break;
                        }
                    }
                }
            }
            // 異なる場へ移動
            else {
                Command com = new Command { Type = CommandType.Jump, Card = card, ToArea = cursor.Area };
                if (cursor.Area == AreaType.Nodes || cursor.Area == AreaType.Deck) { com.FaceSide = false; }
                if (cursor.Area == AreaType.Grave || cursor.Area == AreaType.Hands) { com.FaceSide = true; com.Active = true; }
                if (cursor.Area == AreaType.Field && Area == AreaType.Hands) { com.Type = CommandType.Play; }
                if (cursor.Area == AreaType.Nodes && Area == AreaType.Hands) { com.Active = true; }
                if (cursor.Area == AreaType.Nodes && Area == AreaType.Field) { com.Active = Active; }
                if (cursor.Area == AreaType.Nodes) { com.Location = Player.Nodes.GetEmptyLocation(card); }
                if (cursor.Area == AreaType.Field || cursor.Area == AreaType.Nodes) {
                    Point xy = Player.Areas[cursor.Area].PointToClient(cursor.ScreenRect.Location);
                    com.Location = GetVirtualPoint(xy, Player.Areas[cursor.Area].Size);
                }
                Player.SendCommand(com);
                Player.ClickTime.AddMinutes(-1);
                return;
            }


            // ダブルクリック
            if (Player.ClickCard == card && ( DateTime.Now - Player.ClickTime ).Milliseconds < Properties.Settings.Default.DobleClickInterval) {
                Player.ExecDoubleClick(card);
            }
            Player.ClickTime = DateTime.Now;
            Player.ClickCard = card;
        }
        #endregion
    }



}