using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using MessagePack;

namespace GameMessage.LPBaoWang
{
    
    [MessagePackObject]
    public struct PlayOutCardShang
    {
        /// <summary>
        /// 牌的位置从1开始
        /// </summary>
        [Key(0)]
        public byte Pos;

        /// <summary>
        /// 牌的类型
        /// </summary>
        [Key(1)]
        public CardType1 Type;

        /// <summary>
        /// 牌大小-运算大小
        /// 正的510K 数值是21，副的510K是20
        /// </summary>
        [Key(2)]
        public byte GameNum;

        /// <summary>
        /// 出的牌绝对Id集合
        /// </summary>
        [Key(3)]
        public TCardInfo[] Cards;

        public void Init(int len)
        {
            Cards = new TCardInfo[len];
        }

        public override string ToString()
        {
            return $"pos:{Pos} type:{Type} num:{GameNum} ids:{(Cards == null || Cards.Length <= 0 ? "不要" : string.Join(",", Cards))}";
        }
    }
    
    [MessagePackObject]
    public struct PlayCard
    {
        /// <summary>
        /// 1个玩家的手牌
        /// </summary>
        [Key(0)]
        public TCardInfo[] CardInfos;
        /// <summary>
        /// 初始化玩家牌
        /// </summary>
        public void Init(int len)
        {
            CardInfos = new TCardInfo[len];
        }
    }
    
    [MessagePackObject]
    public struct PlayOutCard : IPlayOutCardType1
    {
        /// <summary>
        /// 牌的位置从1开始
        /// </summary>
        [Key(0)]
        public byte Pos { get; set; }

        /// <summary>
        /// 牌的类型
        /// </summary>
        [Key(1)]
        public CardType1 Type { get; set; }

        /// <summary>
        /// 牌大小-运算大小
        /// 正的510K 数值是21，副的510K是20
        /// </summary>
        [Key(2)]
        public byte GameNum { get; set; }

        /// <summary>
        /// 出的牌绝对Id集合
        /// </summary>
        [Key(3)]
        public byte[] Ids { get; set; }

        public void Init(int len)
        {
            Ids = new byte[len];
        }

        public override string ToString()
        {
            return $"pos:{Pos} type:{Type} num:{GameNum} ids:{(Ids == null || Ids.Length <= 0 ? "不要" :($"len:{Ids.Length}--{string.Join(",", Ids)}"))}";
        }
    }
    
    [MessagePackObject]
    public struct TCardInfo : ICardInfoType1
    {
        /// <summary>
        /// 绝对ID
        /// </summary>
        [Key(0)]
        public byte ID { get; set; }

        /// <summary>
        /// 牌面花色 1黑桃 2红桃 3梅花 4方块 5大小王
        /// </summary>
        [Key(1)] public byte Flower;

        /// <summary>
        /// 牌面大小
        /// 1-13 黑桃A-K
        /// 14-26 红桃A-K
        /// 27-39 梅花A-K
        /// 40-52 方块A-K
        /// 53小王 54大王
        /// </summary>
        [Key(2)] public byte Num;

        /// <summary>
        /// 游戏里大小 3-14（3~A） 16是2  98小王 100大王
        /// </summary>
        [Key(3)]
        public byte GameNum { get; set; }

        /// <summary>
        /// 游戏分值
        /// </summary>
        [Key(4)] public byte Score;

        /// <summary>
        /// 当前在谁手里 1-4
        /// </summary>
        [Key(5)] public byte GameOwer;

        /// <summary>
        /// 状态 0打下去了 1没有打下去
        /// </summary>
        [Key(6)] public byte GameState;

        public override string ToString()
        {
            return
                $"ID:{ID} 花色:{(Flower == 1 ? "黑桃" : Flower == 2 ? "红桃" : Flower == 3 ? "梅花" : Flower == 4 ? "方块" : "王")} 大小:{Num}_{GameNum} 分:{Score} 状态:{(GameState == 1 ? "在手上" : "打下去了")}";
        }

        public bool IsActive()
        {
            return ID > 0 && Flower > 0 && GameNum > 0;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is TCardInfo))
            {
                return false;
            }

            TCardInfo other = (TCardInfo)obj;
            return /*ID == other.ID &&*/
                Flower == other.Flower &&
                Num == other.Num &&
                GameNum == other.GameNum &&
                Score == other.Score &&
                GameOwer == other.GameOwer &&
                GameState == other.GameState;
        }

        public override int GetHashCode()
        {
            int hash = 17;
            //hash = hash * 23 + ID.GetHashCode();
            hash = hash * 22 + Flower.GetHashCode();
            hash = hash * 33 + Num.GetHashCode();
            hash = hash * 24 + GameNum.GetHashCode();
            hash = hash * 11 + Score.GetHashCode();
            hash = hash * 12 + GameOwer.GetHashCode();
            hash = hash * 15 + GameState.GetHashCode();
            return hash;
        }
    }
    
    /// <summary>
    /// 乐平包王游戏包
    /// </summary>
    [MessagePackObject]
    public struct BaoWangGamePack
    {
        /// <summary>
        /// 逻辑内存包
        /// </summary>
        [Key(0)]
        public BaoWangLogicInfo Info;

        /// <summary>
        /// 牌的内存包
        /// </summary>
        [Key(1)]
        public PlayCard[] PlayCard;

        /// <summary>
        /// 规则
        /// </summary>
        [Key(2)]
        public Rule Rule;

        public void Init(byte num)
        {
            Info = new BaoWangLogicInfo();
            PlayCard = null;
            Info.Init(num);
            PlayCard = new PlayCard[num];
        }
    }

    [MessagePackObject]
    public struct BaoWangLogicInfo
    {
        /// <summary>
        /// 游戏流程 1游戏开始 2游戏发牌 3是否投降 4打牌 5结束
        /// </summary>
        [Key(0)]
        public byte GameZT;

        /// <summary>
        /// 游戏人数
        /// </summary>
        [Key(1)]
        public byte PlayerNum;

        /// <summary>
        /// 控制权是哪个位置1-4
        /// </summary>
        [Key(2)]
        public byte WhoPlay;

        /// <summary>
        /// 最大的出牌内容
        /// </summary>
        [Key(3)]
        public PlayOutCard MaxPlayCard;

        /// <summary>
        /// 当前出牌内容
        /// 牌型有单张、对子、连对（3对以上）、三张（不带牌）、顺子、炸弹
        /// </summary>
        [Key(4)]
        public PlayOutCard ActivePlayCard;

        /// <summary>
        /// 包王位置 位置从1开始,也是庄家第一个出牌的人
        /// </summary>
        [Key(5)]
        public byte BaoWangPos;

        /// <summary>
        /// 出完牌的人数
        /// </summary>
        [Key(6)]
        public byte OverCount;

        /// <summary>
        /// 记录打完牌的位置 0号位置是头游 1号位置是二游 2-三游 3-四游
        /// </summary>
        [Key(7)]
        public byte[] OverPos;

        /// <summary>
        /// 记录要显示的赏牌。炸弹玩法和打牌过程中如果要显示赏去就要使用它。
        /// </summary>
        [Key(8)]
        public List<PlayOutCardShang> ShangCards;

        /// <summary>
        /// 4个玩家的赏分,打牌过程中和结算都用它，结算会覆盖打牌过程中的值
        /// </summary>
        [Key(9)]
        public byte[] ShangScore;

        /// <summary>
        /// 赏分输赢记录
        /// </summary>
        [Key(10)]
        public sbyte[] ShangTotalScore;

        /// <summary>
        /// 牌局输赢分，炸弹玩法该值没有
        /// </summary>
        [Key(11)]
        public sbyte[] PlayScore;

        /// <summary>
        /// 玩家托管标识 0没有托管 1托管中
        /// </summary>
        [Key(12)]
        public byte[] PlayTuoGauan;

        /// <summary>
        /// 记录庄家是否投降，1投降 2不投降
        /// </summary>
        [Key(13)]
        public byte TouXiang;

        public void Init(byte num)
        {
            this.PlayerNum = num;
            PlayTuoGauan = new byte[num];
            PlayScore = new sbyte[num];
            ShangTotalScore = new sbyte[num];
            ShangScore = new byte[num];
            ShangCards = new List<PlayOutCardShang>(20);
            OverPos = new byte[num];
            MaxPlayCard = new PlayOutCard();
            ActivePlayCard = new PlayOutCard();
        }
    }

    /// <summary>
    /// 乐平包王规则
    /// </summary>
    [MessagePackObject]
    public struct Rule
    {
        /// <summary>
        /// 游戏人数 有2人 3人
        /// </summary>
        [Key(0)]
        public byte PlayerNum;

        /// <summary>
        /// 是否是炸弹模式 false是普通模式 true是炸弹模式
        /// </summary>
        [Key(1)]
        public bool IsBomb;

        /// <summary>
        /// 是否是随机包王 false是轮流包王 true是随机包王   
        /// </summary>
        [Key(2)]
        public bool IsRandomBao;

        /// <summary>
        /// 0无效 1一家过 2两家过   2个人的模式没有这个选项
        /// </summary>
        [Key(3)]
        public byte Guo;

        /// <summary>
        /// 是否可以投降 true可以 false不可以
        /// </summary>
        [Key(4)]
        public bool IsSurrender;

        /// <summary>
        /// 是否捡炸 true是 false不是
        /// </summary>
        [Key(5)]
        public bool IsJianZha;

        /// <summary>
        /// 是否显示剩余牌 true显示 false不显示
        /// </summary>
        [Key(6)]
        public bool IsShowSurplusCard;

        /// <summary>
        /// 托管的分钟 0不托管 其他时间代表托管几分钟
        /// </summary>
        [Key(7)]
        public byte TuoGuanNum;

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append($"人数：{PlayerNum} ");
            if (IsBomb)
            {
                sb.Append(IsBomb ? "炸弹模式" : "普通模式 ");
                return sb.ToString();
            }
            sb.Append(IsRandomBao ? "随机包王 " : "顺序包王 ");
            if (Guo > 0)
            {
                sb.Append(Guo == 1 ? "一家过 " : "两家过 ");
            }
            if (IsSurrender)
            {
                sb.Append("可以投降 ");
            }
            if (IsJianZha)
            {
                sb.Append("捡炸 ");
            }
            if (IsShowSurplusCard)
            {
                sb.Append("显示剩余牌 ");
            }
            if (TuoGuanNum > 0)
            {
                sb.Append($"托管{TuoGuanNum}分钟 ");
            }
            return sb.ToString();
        }
    }
}
