__all__ = ["Rank", "AlternateRank"]

from enum import IntEnum


class Rank(IntEnum):
    """
    Encodes the rank of a suit. The standard values use
    powers of two, however some internal functions use
    an alternative encoding AlternateRank using the
    values 2-14.
    """

    R2 = 0x0004
    R3 = 0x0008
    R4 = 0x0010
    R5 = 0x0020
    R6 = 0x0040
    R7 = 0x0080
    R8 = 0x0100
    R9 = 0x0200
    RT = 0x0400
    RJ = 0x0800
    RQ = 0x1000
    RK = 0x2000
    RA = 0x4000

    @property
    def abbr(self) -> str:
        return self.name[1]

    @staticmethod
    def find(value: str) -> "Rank":
        try:
            return Rank[f"R{value.upper()}"]
        except KeyError:
            raise ValueError(f"could not convert '{value}' to Rank")

    def to_alternate(self) -> "AlternateRank":
        # Calculate integer log2
        x, y = self.value, 0
        while True:
            x >>= 1
            if x == 0:
                break
            y += 1
        return AlternateRank(y)


class AlternateRank(IntEnum):
    """
    Encodes the rank of a suit using the values 2-14. Used
    for internal functions, for APIs use the Rank class.
    """

    R2 = 2
    R3 = 3
    R4 = 4
    R5 = 5
    R6 = 6
    R7 = 7
    R8 = 8
    R9 = 9
    RT = 10
    RJ = 11
    RQ = 12
    RK = 13
    RA = 14

    @property
    def abbr(self) -> str:
        return self.name[1]

    @staticmethod
    def find(value: str) -> "AlternateRank":
        try:
            return AlternateRank[f"R{value.upper()}"]
        except KeyError:
            raise ValueError(f"could not convert '{value}' to AlternateRank")

    def to_standard(self) -> Rank:
        # Calculate integer power of 2
        return Rank(2 << (self.value - 1))
