#!/usr/bin/env python3

"""
32blit sprite file format

# 12 byte common header

- 8: Type of file identifier ("SPRITEPK", "SPRITERW")
- 2: Total file size

# SPRITEPK header (Packed paletted sprite)

A packed sprite can have a variable number of palette colours up to 255.

Data is packed at the number of bits-per-pixel required to index each palette entry.

IE: a two colour image will be packed with 1bpp

- 2: Sprite width
- 2: Sprite height
- 2: Sprite columns
- 2: Sprite rows
- 1: Format (always paletted)
- 1: Palette size
- X * 4: Pallete entries (where X = number of palette entries)
- Y: Image data

Usage: ./sprite-builder packed input-file.png
"input-file.png" should contain no more than 255 colours!

# SPRITERW header (Raw sprite - RGBA, RGB, P or M)

An unpacked sprite is just a block of raw surface data
in either RGBA (4 bytes), RGB (3 bytes) or P/M (1 bytes) format.

Unpacked sprites are *huge* but useful for streaming into the framebuffer from storage.

The max power of two sprite sizes supported by this file format are-

- 64x64 in RGBA and RGB mode
- 128x128 in P mode

- 2: Sprite width
- 2: Sprite height
- 2: Sprite columns
- 2: Sprite rows
- 1: Format (RGBA, RGB, P or M)
- Y: Image data

Usage: ./sprite-builder raw --format RGB565 input-file.png

"""

import argparse
import math
import sys

from bitstring import BitArray
from construct import this, BitStruct, BitsInteger, Struct, Int8ul, Int16ul, Array, PrefixedArray, Computed, Switch, GreedyBytes, Enum, PaddedString
from PIL import Image, ImagePalette


def compute_bit_length(ctx):
    """Compute the required bit length for image data.

    Uses the count of items in the palette to determine how
    densely we can pack the image data.

    """
    if ctx.format == SpriteFormat.enum.p:
        return (len(ctx.palette.colours) - 1).bit_length()
    elif ctx.format == SpriteFormat.enum.rgba:
        return 32
    elif ctx.format == SpriteFormat.enum.rgb:
        return 24
    else:
        return 0


def compute_data_length(ctx):
    """Compute the required data length for palette based images.

    We need this computation here so we can use `math.ceil` and
    byte-align the result.

    """
    if ctx.format == SpriteFormat.enum.p:
        return math.ceil((ctx.width * ctx.height * ctx.bit_length) / 8)
    else:
        return ctx.width * ctx.height


class SmartEnum(Enum):
    """Fudge to support SpriteFormat.enum.p etc"""
    def __init__(self, *args, **kwargs):
        Enum.__init__(self, *args, **kwargs)

        class x():
            pass
        self.enum = x()
        for e in self.encmapping.keys():
            self.enum.__dict__[e] = e


AssetType = Enum(PaddedString(8, "utf8"), packed='SPRITEPK', raw='SPRITERW')

SpriteFormat = SmartEnum(
    Int8ul,
    rgb=0,
    rgba=1,
    p=2,
    m=3
)

asset_rgba = Struct(
    'r' / Int8ul,
    'g' / Int8ul,
    'b' / Int8ul,
    'a' / Int8ul
)

asset_rgb = Struct(
    'r' / Int8ul,
    'g' / Int8ul,
    'b' / Int8ul
)

asset_packed = Struct(
    'width' / Int16ul,
    'height' / Int16ul,
    'columns' / Int16ul,
    'rows' / Int16ul,
    'format' / SpriteFormat,
    'palette' / Struct(
        'colours' / PrefixedArray(Int8ul, asset_rgba),
    ),
    'bit_length' / Computed(compute_bit_length),
    'data_length' / Computed(compute_data_length),
    'data' / Array(this.data_length, Int8ul)
)

asset_raw = Struct( 
    'width' / Int16ul,
    'height' / Int16ul,
    'columns' / Int16ul,
    'rows' / Int16ul,
    'format' / SpriteFormat,
    'bit_length' / Computed(compute_bit_length),
    'data_length' / Computed(compute_data_length),
    'data' / Switch(this.format, {
        'rgba': Array(this.data_length, asset_rgba),
        'rgb': Array(this.data_length, asset_rgb),
        'p': Array(this.data_length, Int8ul),
        'm': Array(this.data_length, Int8ul)
    })
)

asset = Struct(
    'header' / Struct(
        'type' / AssetType,
        'size' / Int16ul,
    ),
    'data' / GreedyBytes
)

typemap = {
    'packed': asset_packed,
    'raw': asset_raw
}


def unpack_asset(asset_data):
    unpacked = asset.parse(asset_data)
    builder = typemap[unpacked.header.type]
    return builder.parse(unpacked.data)


def build_asset(asset_type, asset_data):
    builder = typemap[asset_type]
    packed = builder.build(asset_data)
    total_size = len(packed) + asset.header.sizeof()
    if total_size > 65535:
        raise RuntimeError("Sprite exceeds maximum filesize: {} > 65535".format(total_size))
    return asset.build(dict(
        header=dict(
            type=asset_type,
            size=total_size,
        ),
        data=packed
    ))


def color(r, g, b, a=None):
    a = 0xff if a is None else a
    return dict(r=r, g=g, b=b, a=a)


def rgba_string(c):
    return "rgba({r}, {g}, {b}, {a})".format(**c)


def format_hex(data):
    return ', '.join(['0x{:02x}'.format(x) for x in data])


def load_palette(image):
    palette_colours = []

    if image.palette is None:
        # Divine the palette from the individual pixels in the image
        # they will be inserted into our target palette in the order
        # found in the palette image
        mode = image.mode
        w, h = image.size

        if mode in ['RGB', 'RGBA']:
            for y in range(h):
                for x in range(w):
                    # The spread operator will take both RGB and RGBA
                    # tuples and pass them into color() properly.
                    c = color(*image.getpixel((x, y)))
                    if c not in palette_colours:
                        palette_colours.append(c)

        else:
            raise RuntimeError(f"Unsupported image mode: {mode}")

    else:
        mode, palette = image.palette.getdata()
        palette = list(palette)
        if mode == 'RGB':
            for x in range(len(palette) // 3):
                r, g, b = palette[x * 3:(x * 3) + 3]
                palette_colours.append(color(r, g, b))

        elif mode == 'RGBA':
            for x in range(len(palette) // 4):
                r, g, b, a = palette[x * 4:(x * 4) + 4]
                palette_colours.append(color(r, g, b, a))

    if len(palette_colours) > 255:
        raise RuntimeError(f"Too many colours in palette! ({len(palette_colours)})")

    return palette_colours


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--nowarn', action='store_true', help='Suppress deprecation warning')
    subparsers = parser.add_subparsers(help='Commands', dest='command')
    parser_packed = subparsers.add_parser('packed', help='Process an image file into a paletted 32blit sprite')
    parser_raw = subparsers.add_parser('raw', help='Process an image file into a raw (rgba, rgb) 32blit sprite')

    parser.add_argument('--out', type=str, help='set output filename (default <inputfile>.blit)', default=None)
    parser.add_argument('file', type=str, help='input file')

    # The engine presently only supports 8x8 tile sizes
    parser.add_argument('--tilesizex', type=int, help='tile size x', default=8)
    parser.add_argument('--tilesizey', type=int, help='tile size y', default=8)

    # Allow for naming of the resulting packed_data array
    parser_packed.add_argument('--arrayname', type=str, help='set output array name (default <packed_data>)', default='packed_data')

    # Raw input can be given as any image type, and will be packed into:
    # * RGBA (full fidelity)
    # * RGB888 (discard alpha)
    # * RGB565 (discard alpha, convert colours with bitshift: R >> 3, G >> 2 B >> 3)
    parser_raw.add_argument('--format', type=str, choices=('RGBA', 'RGB'), help='raw data output format', default='RGBA')

    # A palette file should be a PNG file containing a series of pixels in the desired colours and order of the output palette.
    # If it's indexed, 8bpp colour then its palette will be used directly, otherwise the pixel data will be converted automatically.
    parser_packed.add_argument('--palette', type=str, help='image or palette file', default=None)

    args = parser.parse_args()

    if not args.nowarn:
        print('''
This tool has been deprecated in favour of https://github.com/pimoroni/32blit-tools
Run with --nowarn to hide this message.
''')

    source_image = Image.open(args.file)

    if args.command == 'raw':
        # Make sure we're always working with the same type of image
        source_image = source_image.convert('RGBA')

        raw_data = []

        for y in range(source_image.height):
            for x in range(source_image.width):
                r, g, b, a = source_image.getpixel((x, y))
                if args.format == 'RGBA':
                    raw_data.append({'r': r, 'g': g, 'b': b, 'a': a})
                if args.format == 'RGB':
                    raw_data.append({'r': r, 'g': g, 'b': b})

        raw = build_asset(
            'raw',
            dict(
                width=source_image.width,
                height=source_image.height,
                columns=source_image.width // args.tilesizex,
                rows=source_image.height // args.tilesizey,
                format=args.format.lower(),
                data=raw_data
            )
        )

        if args.out is not None:
            with open(args.out, 'wb+') as f:
                f.write(raw)
            sys.exit(0)

    if args.command == 'packed':
        target_image = source_image
        source_mode = source_image.mode
        source_palette_colours = load_palette(source_image)
        target_palette_colours = source_palette_colours

        bit_length = (len(source_palette_colours) - 1).bit_length()

        if source_mode == 'P':
            if args.palette is not None:
                palette_image = Image.open(args.palette)
                target_palette_colours = load_palette(palette_image)

                w, h = source_image.size
                for y in range(h):
                    for x in range(w):
                        p = source_image.getpixel((x, y))
                        c = source_palette_colours[p]
                        try:
                            new_p = target_palette_colours.index(c)
                            target_image.putpixel((x, y), new_p)
                        except ValueError:
                            raise RuntimeError("Colour {},{},{},{} not found in target palette!".format(*c.rgba()))

                source_palette_colours = target_palette_colours
        else:
            target_image = Image.new('P', source_image.size)
            w, h = source_image.size
            for y in range(h):
                for x in range(w):
                    if source_mode == 'RGBA':
                        r, g, b, a = source_image.getpixel((x, y))
                        c = color(r, g, b, a)
                    elif source_mode == 'RGB':
                        r, g, b = source_image.getpixel((x, y))
                        c = color(r, g, b)

                    try:
                        new_p = target_palette_colours.index(c)
                        target_image.putpixel((x, y), new_p)
                    except ValueError:
                        raise RuntimeError("Colour {},{},{},{} not found in target palette!".format(*c.rgba()))



        packed_image_data = BitArray().join(BitArray(uint=x, length=bit_length) for x in target_image.tobytes()).tobytes()

        packed = build_asset(
            'packed',
            dict(
                width=target_image.width,
                height=target_image.height,
                columns=target_image.width // args.tilesizex,
                rows=target_image.height // args.tilesizey,
                format='p',
                palette=dict(
                    colours=source_palette_colours
                ),
                data=packed_image_data
            )
        )

        if args.out is not None:
            with open(args.out, 'wb+') as f:
                f.write(packed)
            sys.exit(0)

        packed = list(packed)
        formatted_data = []
        formatted_palette = []
        row_width = 16

        HEADER_SIZE = 20

        PALETTE_SIZE = len(source_palette_colours) * 4

        palette_data = packed[HEADER_SIZE:HEADER_SIZE + PALETTE_SIZE]
        for x in range(0, math.ceil(len(palette_data) / 4)):
            offset = x * 4
            current_row = palette_data[offset:offset + 4]
            formatted_palette.append(format_hex(current_row))

        packed_data = packed[HEADER_SIZE + PALETTE_SIZE:]
        for x in range(0, math.ceil(len(packed_data) / float(row_width))):
            offset = x * row_width
            current_row = packed_data[offset:offset + row_width]
            formatted_data.append(format_hex(current_row))

        print("""
uint8_t {array_name}[] = {{
    {type}, // type: spritepk (packed, paletted sprite)
    {payload_size}, // payload size ({comment_payload_size})

    {width}, // width ({comment_width})
    {height}, // height ({comment_height})
    {cols}, // cols ({comment_cols})
    {rows}, // rows ({comment_rows})

    {format}, // format (paletted)

    {colours}, // number of palette colours ({number_of_colours})
//  r     g     b     a
    {palette},

    {data}
}};
""".format(
            array_name=args.arrayname,
            type=format_hex(packed[0:8]),
            payload_size=format_hex(packed[8:10]),
            comment_payload_size=len(packed),
            width=format_hex(packed[10:12]),
            comment_width=target_image.width,
            height=format_hex(packed[12:14]),
            comment_height=target_image.height,
            cols=format_hex(packed[14:16]),
            comment_cols=target_image.width // args.tilesizex,
            rows=format_hex(packed[16:18]),
            comment_rows=target_image.height // args.tilesizey,
            format=format_hex(packed[18:19]),
            colours=format_hex(packed[19:20]),
            number_of_colours=packed[19:20][0],
            data=',\n    '.join(formatted_data),
            palette=',\n    '.join(formatted_palette)
        ))
