using MessagePack;
using System;
using System.Collections;
using System.Collections.Generic;


namespace GameMessage.ShiSanShui
{

    /// <summary>
    /// 十三水包类型
    /// </summary>
    [MessagePackObject()]
    public class SssPackType
    {
        /// <summary>
        /// 全包
        /// </summary>
        [Key(0)]
        public const byte AllPack = 1;

        /// <summary>
        /// 操作包
        /// </summary>
        [Key(1)]
        public const byte OperationPack = 2;

        /// <summary>
        /// 比牌包
        /// </summary>
        [Key(2)]
        public const byte ComparePack = 3;

        /// <summary>
        /// 结算包
        /// </summary>
        [Key(3)]
        public const byte SettlementPack = 4;

        /// <summary>
        /// 切换状态包
        /// </summary>
        [Key(4)]
        public const byte ChangeStatePack = 5;

        /// <summary>
        /// 玩家准备包
        /// </summary>
        [Key(5)]
        public const byte PlayerReadyPack =6;

        /// <summary>
        /// 游戏结束包，客户端通知服务器结束
        /// </summary>
        [Key(6)]
        public const byte GameOverPack = 7;

        /// <summary>
        /// 奖池包
        /// </summary>
        [Key(7)]
        public const byte GoldPoolPack = 8;

        /// <summary>
        /// 游戏规则包
        /// </summary>
        [Key(8)]
        public const byte GameRulePack = 9;

        /// <summary>
        /// 游戏总结算包
        /// </summary>
        [Key(9)]
        public const byte AllGameOverPack = 10;
    }

    /// <summary>
    /// 十三水总包
    /// </summary>
    [MessagePackObject()]
    public class SssAllPack
    {
        /// <summary>
        /// 游戏阶段
        /// </summary>
        [Key(0)]
        public int Stage;

        /// <summary>
        /// 自身位置
        /// </summary>
        [Key(1)]
        public int SelfPos;

        /// <summary>
        /// 手牌
        /// </summary>
        [Key(2)]
        public List<SssCard> HandCards;

        /// <summary>
        /// 所有人出牌消息,第一个下标为道数
        /// </summary>
        [Key(3)]
        public PublicInfo[][] AllOutCardInfo;

        /// <summary>
        /// 结算信息
        /// </summary>
        [Key(4)]
        public SettlementItem[] OverInfo;

        /// <summary>
        /// 当前比较道数 1前道 2中道 3尾道
        /// </summary>
        [Key(5)]
        public int CurrentCompareLevel;

        /// <summary>
        /// 每道各个玩家的分数
        /// </summary>
        [Key(6)]
        public int[][] AllWayScores;

        /// <summary>
        /// 玩家数量
        /// </summary>
        [Key(7)]
        public int PlayerCount;

        /// <summary>
        /// 奖金数，子数，需要乘上房间倍率
        /// </summary>
        [Key(8)]
        public int GoldPool;

        /// <summary>
        /// MVP信息,下标为位置，值是MVP几
        /// </summary>
        [Key(9)]
        public int[] MVP;

        /// <summary>
        /// 剩余牌
        /// </summary>
        [Key(10)]
        public List<SssCard> RemainCards;



        public SssAllPack()
        {
            AllOutCardInfo = new PublicInfo[3][];
            AllWayScores = new int[3][];
            HandCards = new List<SssCard>();
            RemainCards = new List<SssCard>();
        }
    }


    /// <summary>
    /// 公共消息
    /// </summary>
    [MessagePackObject]
    public class PublicInfo
    {
        /// <summary>
        /// 1 - 头道 2 - 中道 3 - 尾道
        /// </summary>
        [Key(0)]
        public int Rest;

        /// <summary>
        /// 牌型信息
        /// </summary>
        [Key(1)]
        public CardInfo PlayArea;

        /// <summary>
        /// 特殊牌型
        /// </summary>
        [Key(2)]
        public int SpecialPattern;

        /// <summary>
        /// 排名
        /// </summary>
        [Key(3)]
        public int Rank;


        public PublicInfo()
        {
            PlayArea = new CardInfo();
        }
    }

    /// <summary>
    /// 牌型信息
    /// </summary>
    [MessagePackObject]
    public class CardInfo
    {
        /// <summary>
        /// 牌型
        /// </summary>
        [Key(0)]
        public int Style;

        /// <summary>
        /// 出牌
        /// </summary>
        [Key(1)]
        public List<SssCard> OutCard;


        public CardInfo()
        {
            OutCard = new List<SssCard>();
        }

        public CardInfo(int style, List<SssCard> cards)
        {
            Style = style;
            OutCard = cards;
        }
    }

    /// <summary>
    /// 单个结算信息
    /// </summary>
    [MessagePackObject]
    public class SettlementItem
    {
        /// <summary>
        /// 位置
        /// </summary>
        [Key(0)]
        public int Pos;

        /// <summary>
        /// 总输赢，多少个子
        /// </summary>
        [Key(1)]
        public int TotalNum;

        /// <summary>
        /// 打枪位置
        /// </summary>
        [Key(2)]
        public List<int> WinSeat;

        /// <summary>
        /// MVP次数
        /// </summary>
        [Key(3)]
        public int MVPCount;

        /// <summary>
        /// 赢得每个玩家的分数
        /// </summary>
        [Key(4)]
        public int[] WinScore;
    }


    /// <summary>
    /// 十三水操作包，玩家发给服务器
    /// </summary>
    [MessagePackObject()]
    public class SssOperationPack
    {
        /// <summary>
        /// 头道
        /// </summary>
        [Key(0)]
        public List<SssCard> HeadWay;

        /// <summary>
        /// 中道
        /// </summary>
        [Key(1)]
        public List<SssCard> MiddleWay;

        /// <summary>
        /// 尾道
        /// </summary>
        [Key(2)]
        public List<SssCard> EndWay;

        /// <summary>
        /// 特殊牌型
        /// </summary>
        [Key(3)]
        public int SpecialPattern;
    }

    /// <summary>
    /// 十三水准备包
    /// </summary>
    [MessagePackObject()]
    public class SssReadyPack
    {
        /// <summary>
        /// 准备的玩家座位
        /// </summary>
        [Key(0)]
        public int ReadySeat;
    }

    /// <summary>
    /// 十三水玩家每道出牌信息包,服务器下发
    /// </summary>
    [MessagePackObject()]
    public class SssComparePack
    {
        /// <summary>
        /// 玩家每道出牌信息
        /// </summary>
        [Key(0)]
        public PublicInfo[] PlayerOutInfos;

        /// <summary>
        /// 玩家每道得分
        /// </summary>
        [Key(1)]
        public int[] CurrentWayScores;

        /// <summary>
        /// 当前道数
        /// </summary>
        [Key(2)]
        public int Way;
    }

    /// <summary>
    /// 十三水结算包
    /// </summary>
    [MessagePackObject()]
    public class SssSettlePack
    {
        /// <summary>
        /// 玩家结算信息
        /// </summary>
        [Key(0)]
        public SettlementItem[] OverInfo;

        /// <summary>
        /// 牌库剩余牌
        /// </summary>
        [Key(1)]
        public List<SssCard> RemainCards;
    }


    /// <summary>
    /// 十三水切换状态包
    /// </summary>
    [MessagePackObject()]
    public class SssChangeStatePack
    {
        /// <summary>
        /// 游戏状态
        /// </summary>
        [Key(0)]
        public int State;
    }

    /// <summary>
    /// 十三水奖池包
    /// </summary>
    [MessagePackObject()]
    public class SssGoldPoolPack
    {
        /// <summary>
        /// 玩家座位号
        /// </summary>
        [Key(0)]
        public List<int> Seat;

        /// <summary>
        /// 奖池金额，子数
        /// </summary>
        [Key(1)]
        public int GoldPool;
    }

    /// <summary>
    /// 十三水规则包
    /// </summary>
    [MessagePackObject()]
    public class SssRulePack
    {
        /// <summary>
        /// 规则号
        /// </summary>
        [Key(0)]
        public string Rule;


    }



    /// <summary>
    /// 牌型
    /// </summary>
    public enum CardStyle
    {
        /// <summary>
        /// 无效牌
        /// </summary>
        None = 0,

        /// <summary>
        /// 乌龙/高牌
        /// </summary>
        HighCard = 1,

        /// <summary>
        /// 一对
        /// </summary>
        OnePair = 2,

        /// <summary>
        /// 两对
        /// </summary>
        TwoPair = 3,

        /// <summary>
        /// 三张
        /// </summary>
        ThreeOfAKind = 4,

        /// <summary>
        /// 双鬼头道
        /// </summary>
        ShuangGuiTouDao = 5,

        /// <summary>
        /// 三鬼
        /// </summary>
        SanGui = 6,

        /// <summary>
        /// 顺子
        /// </summary>
        Straight = 7,

        /// <summary>
        /// 同花
        /// </summary>
        Flush = 8,

        /// <summary>
        /// 葫芦
        /// </summary>
        FullHouse = 9,

        /// <summary>
        /// 铁支
        /// </summary>
        FourOfAKind = 10,

        /// <summary>
        /// 同花顺
        /// </summary>
        StraightFlush = 11,

        /// <summary>
        /// 五同
        /// </summary>
        FiveOfAKind = 12,

        /// <summary>
        /// 六同
        /// </summary>
        SixOfKind = 13,

        /// <summary>
        /// 五鬼
        /// </summary>
        WuGui = 14,
    }


    /// <summary>
    /// 游戏阶段`
    /// </summary>
    public enum GameStage : int
    {
        None = 0,
        GameBegin = 1,  //游戏开始阶段
        Double,         //加倍阶段
        SelectCard,     //选牌阶段
        GamePlay,       //比牌阶段
        EpisodeOver,    //小局结束阶段
        Settlement,     //游戏结算阶段
        GameOver        //结束阶段
    }


    [Serializable]
    [MessagePackObject]
    public class SssCard
    {
        /// <summary>
        /// Id 是从1开始到54
        /// </summary>
        [Key(0)]
        public int Id;

        [Key(1)]
        public Suit Flower;

        /// <summary>
        /// 14-A 15 小王 - 16 大王
        /// </summary>
        [Key(2)]
        public int Num;

        [Key(3)]
        public int ASCII;

        [Key(4)]
        public int Score;

        [Key(5)]
        public SssCard Joker;

        public SssCard() { }


        public SssCard(int num, Suit flower, bool isJoker = false)
        {
            if (num == 15)
                this.Id = 53;
            else if (num == 16)
                this.Id = 54;
            else
            {
                this.Id = ((int)(flower - 1) * 13 + (num - 1));
            }

            if (this.Id <= 0)
            {
                this.Id = 0;
            }

            // 如果是鬼牌花色且不是真正的鬼牌，则创建鬼牌对象
            if ((flower == Suit.Joker || flower == Suit.LaiZi) && !isJoker)
            {
                this.Joker = new SssCard(num, flower, true);
                this.Num = this.Joker.Num;
                this.Flower = this.Joker.Flower;
                this.Score = this.Joker.Score;
                this.ASCII = this.Joker.ASCII;
                return;
            }
            this.Joker = null;
            this.Num = num;
            this.Flower = flower;
            this.ASCII = 16 * ((int)flower - 1) + num;
            this.Score = PokerPointToShiSanShuiScore();
        }



        public bool IsJoker()
        {
            return this.Id >= 53;
        }

        public int PokerPointToShiSanShuiScore()
        {
            return this.Num;
        }

        public override string ToString()
        {
            var suitStr = string.Empty;
            switch (Flower)
            {
                case Suit.Spade:
                    suitStr = "黑桃";
                    break;
                case Suit.Heart:
                    suitStr = "红心";
                    break;
                case Suit.Club:
                    suitStr = "梅花";
                    break;
                case Suit.Diamond:
                    suitStr = "方块";
                    break;
                case Suit.Joker:
                    return (Num == 15 ? "小王" : "大王");
                case Suit.LaiZi:
                    return "癞子";
                default:
                    throw new ArgumentOutOfRangeException(nameof(Flower));
            }
            var valueStr = string.Empty;
            switch (Num)
            {
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                case 9:
                case 10: valueStr = Num.ToString().PadRight(2, ' '); break;
                case 11: valueStr = "J "; break;
                case 12: valueStr = "Q "; break;
                case 13: valueStr = "K "; break;
                case 14: valueStr = "A "; break;
                default: throw new ArgumentOutOfRangeException(nameof(Num));
            }
            return Id + suitStr + valueStr;
        }

        /// <summary>
        /// 王当癞子
        /// </summary>
        public void JokerChange(int num, Suit flower)
        {
            //id不会变，还是王的ID
            this.Num = num;
            this.Flower = flower;
            this.ASCII = 16 * ((int)flower - 1) + num;
            this.Score = this.PokerPointToShiSanShuiScore();
        }
    }


    /// <summary>
    /// 扑克花色
    /// </summary>
    [Serializable]
    public enum Suit : int
    {
        /// <summary>
        /// 方块
        /// </summary>
        Diamond = 1,

        /// <summary>
        /// 梅花
        /// </summary>
        Club = 2,

        /// <summary>
        /// 红桃
        /// </summary>
        Heart = 3,

        /// <summary>
        /// 黑桃
        /// </summary>
        Spade = 4,

        /// <summary>
        /// 王
        /// </summary>
        Joker = 5,

        /// <summary>
        /// 癞子
        /// </summary>
        LaiZi = 6,
    }

    /// <summary>
    /// 扑克面值
    /// </summary>
    public enum PokerPoint : int
    {
        Two = 2,
        Three = 3,
        Four = 4,
        Five = 5,
        Six = 6,
        Seven = 7,
        Eight = 8,
        Nine = 9,
        Ten = 10,
        J = 11,
        Q = 12,
        K = 13,
        A = 14,
        /// <summary>
        /// 小王
        /// </summary>
        SJoker = 15,
        /// <summary>
        /// 大王
        /// </summary>
        BJoker = 16,
    }

}

