import ctypes


class _CONSOLE_SCREEN_BUFFER_INFO_EX(ctypes.Structure):
    _fields_ = [("cbSize", ctypes.c_int),
                ("dwSizeX", ctypes.c_short),
                ("dwSizeY", ctypes.c_short),
                ("dwCursorPositionX", ctypes.c_short),
                ("dwCursorPositionY", ctypes.c_short),
                ("wAttributes", ctypes.c_ushort),
                ("srWindowL", ctypes.c_short),
                ("srWindowT", ctypes.c_short),
                ("srWindowR", ctypes.c_short),
                ("srWindowB", ctypes.c_short),
                ("dwMaximumWindowSizeX", ctypes.c_short),
                ("dwMaximumWindowSizeY", ctypes.c_short),
                ("wPopupAttributes", ctypes.c_ushort),
                ("bFullscreenSupported", ctypes.c_bool),
                ("black", ctypes.c_uint),
                ("darkBlue", ctypes.c_uint),
                ("darkGreen", ctypes.c_uint),
                ("darkCyan", ctypes.c_uint),
                ("darkRed", ctypes.c_uint),
                ("darkMagenta", ctypes.c_uint),
                ("darkYellow", ctypes.c_uint),
                ("gray", ctypes.c_uint),
                ("darkGray", ctypes.c_uint),
                ("blue", ctypes.c_uint),
                ("green", ctypes.c_uint),
                ("cyan", ctypes.c_uint),
                ("red", ctypes.c_uint),
                ("magenta", ctypes.c_uint),
                ("yellow", ctypes.c_uint),
                ("white", ctypes.c_uint)]


class Palette:
    GAME_PALETTE = {'black': 0x00000000,
                    'darkBlue': 0x00800000,
                    'darkGreen': 0x00008CFF,  # Orange
                    'darkCyan': 0x00523845,  # Razmi hair
                    'darkRed': 0x004678D2,  # Chopsticks
                    'darkMagenta': 0x00C4DFFF,  # Light skin tone
                    'darkYellow': 0x0000FFFF,  # Bright yellow (so we save a few Style.BRIGHT tags)
                    'gray': 0x00C0C0C0,
                    'darkGray': 0x00808080,
                    'blue': 0x00FF8C5A, # Rodney bowl blue
                    'green': 0x0000FF00,
                    'cyan': 0x00FFFF00,
                    'red': 0x000000FF,
                    'magenta': 0x00523845,  # Same as Ramzi hair, used for the foreground
                    'yellow': 0x0000FFFF,
                    'white': 0x00FFFFFF}

    DEFAULT_PALETTE = {'black': 0x00000000,
                       'darkBlue': 0x00800000,
                       'darkGreen': 0x00008000,
                       'darkCyan': 0x00808000,
                       'darkRed': 0x00000080,
                       'darkMagenta': 0x00800080,
                       'darkYellow': 0x00008080,
                       'gray': 0x00C0C0C0,
                       'darkGray': 0x00808080,
                       'blue': 0x00FF0000,
                       'green': 0x0000FF00,
                       'cyan': 0x00FFFF00,
                       'red': 0x000000FF,
                       'magenta': 0x00FF00FF,
                       'yellow': 0x0000FFFF,
                       'white': 0x00FFFFFF}

    @staticmethod
    def set_palette(palette=None):
        """
        TODO Support for XP and older is possible: http://stackoverflow.com/questions/13486585/getconsolescreenbufferinfoex-equivalent-for-windows-xp
        Set command line color palette (windows cmd only)
        :param palette: see default palette in this method
        """
        # Change console color TODO untested if it affects previous output, but my guess is that it does
        if palette is None:
            # Set default palette
            palette = Palette.DEFAULT_PALETTE

        handle = ctypes.windll.kernel32.GetStdHandle(-11)
        csbie = _CONSOLE_SCREEN_BUFFER_INFO_EX()
        csbie.cbSize = 96
        ctypes.windll.kernel32.GetConsoleScreenBufferInfoEx(handle, ctypes.byref(csbie))
        # Set all colors from palette
        csbie.black = palette['black']
        csbie.darkBlue = palette['darkBlue']
        csbie.darkGreen = palette['darkGreen']
        csbie.darkCyan = palette['darkCyan']
        csbie.darkRed = palette['darkRed']
        csbie.darkMagenta = palette['darkMagenta']
        csbie.darkYellow = palette['darkYellow']
        csbie.gray = palette['gray']
        csbie.darkGray = palette['darkGray']
        csbie.blue = palette['blue']
        csbie.green = palette['green']
        csbie.cyan = palette['cyan']
        csbie.red = palette['red']
        csbie.magenta = palette['magenta']
        csbie.yellow = palette['yellow']
        csbie.white = palette['white']
        # Write them back
        ctypes.windll.kernel32.SetConsoleScreenBufferInfoEx(handle, ctypes.byref(csbie))
