using System;
using System.Linq;

namespace GameFix.Poker
{
    /// <summary>
    /// 一张牌
    /// </summary>
    public class Card
    {
        public int Id { get; }
        
        public byte CardType { get; set; }

        /// <summary>
        /// 逻辑值
        /// </summary>
        public byte Value { get; private set; }
        
        /// <summary>
        /// 花色
        /// </summary>
        public byte Suit { get; private set; }

        /// <summary>
        /// 排序数
        /// </summary>
        public int SortNum { get;private set; }
        
        /// <summary>
        /// 原始逻辑值
        /// </summary>
        public byte OriginValue { get; private set; }
        
        /// <summary>
        /// 用户数据
        /// </summary>
        public object UserData { get; set; }
        
        public override string ToString()
        {
            var suitStr = string.Empty;
            switch (Suit)
            {
                case DataCardConst.SuitSpade:
                    suitStr = "黑";
                    break;
                case DataCardConst.SuitHeart:
                    suitStr = "红";
                    break;
                case DataCardConst.SuitClub:
                    suitStr = "梅";
                    break;
                case DataCardConst.SuitDiamond:
                    suitStr = "方";
                    break;
                case DataCardConst.SuitJoker:
                    return (Value == DataCardConst.JokerValues[0] ? "小王" : "大王");
                default:
                    return $"CardErr[{Suit}_{Value}]";
            }

            var vIndex = Array.IndexOf(DataCardConst.CardValues, Value);
            if (vIndex<0 || vIndex >= DataCardConst.CardValueText.Length)
                return $"CardErr[{Suit}_{Value}]";
            var valueStr = DataCardConst.CardValueText[vIndex];

            return suitStr + valueStr;
        }
        
        int? _hashCode = null;
        
        public override int GetHashCode() =>
            _hashCode.HasValue ? _hashCode.Value : (_hashCode = Id << 16 | (byte)Suit << 8 | Value).Value;
        
        public Card()
        {
        }
        
        public Card(int id, byte suit, byte value)
        {
            this.Id = id;
            this.Suit = suit;
            this.Value = value;
            this.SortNum = Value * 10 + suit;
        }

        public void SetSortNum(int num)
        {
            this.SortNum = num;
        }
        
        public bool IsLz => CardType == DataCardConst.CardTypeLZ;

        public bool IsReplace => OriginValue != 0;


        /// <summary>
        /// 是否包含某个类型
        /// </summary>
        public bool IsCardType(byte cardType)
        {
            return (CardType & cardType) == cardType;
        }
        
        /// <summary>
        /// 附加一个牌值类型
        /// </summary>
        public void AddOrRmCardType(byte cardType, bool isAdd = true)
        {
            if (isAdd)
            {
                CardType |= cardType;
            }
            else
            {
                CardType &= (byte)~cardType;
            }
        }

        /// <summary>
        /// 癞子可以替换任何牌
        /// </summary>
        public Card Replace(byte value)
        {
            if (CardType == DataCardConst.CardTypeLZ)
            {
                var newCard = this.Clone();
                newCard.OriginValue = Value;
                newCard.Value = value;
                newCard.SortNum = Value * 10 + Suit;
                return newCard;
            }

            return this;
        }
        
        /// <summary>
        /// 浅拷贝
        /// </summary>
        public Card Clone() => (Card)MemberwiseClone();
    }

    public static class CardManager
    {
        /// <summary>
        /// 逻辑数 转 显示数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte LogicValue2UINum(byte value)
        {
            switch (value)
            {
                case 14:
                    return 1;
                case 16:
                    return 2;
                case 18:
                    return 14;
                case 19:
                    return 15;
                default:
                    return value;
            }
        }
        
        public static byte LogicValue2SoundNum(byte value)
        {
            switch (value)
            {
                case 14:
                    return 14;
                case 16:
                    return 15;
                case 18:
                    return 16;
                case 19:
                    return 17;
                default:
                    return value;
            }
        }
        
        public static (byte, byte) GetSuitValueFromStr(string cardString)
        {
            var chars = cardString.Trim().ToCharArray();
            var pos = 0;
            if (char.IsNumber(chars[0])) {
                pos++;
            }
            byte suit = DataCardConst.SuitJoker;
            switch (chars[pos]) {
                case '小': return (DataCardConst.SuitJoker, 18);
                case '大': return (DataCardConst.SuitJoker, 19);
                case '黑': suit = DataCardConst.SuitSpade; break;
                case '梅': suit = DataCardConst.SuitClub; break;
                case '红': suit = DataCardConst.SuitHeart; break;
                case '方': suit = DataCardConst.SuitDiamond; break;
                default: throw new NotSupportedException($"不支持的花色：{chars[0]}");
            }
            pos++;
            var value = byte.MinValue;
            var str = new string(chars.Skip(pos).ToArray()).TrimStart('0').TrimEnd(' ');
            var index = Array.IndexOf(DataCardConst.CardValueText, str);
            if (index >= 0)
            {
                value = DataCardConst.CardValues[index];
            }
            else
            {
                value = byte.Parse(str);
            }
            return (suit, value);
        }

    }
}