#!/usr/bin/python3

import sys

import gif

if len(sys.argv) < 2:
    exit(1)

r = gif.Reader()
r.feed(open(sys.argv[1], "rb").read())

if not r.has_header() or not r.is_gif():
    print("Not a GIF")
    exit()

if not r.has_screen_descriptor():
    print("Too short")
    exit()


def color_to_string(color: tuple[int, int, int]) -> str:
    (red, green, blue) = color
    return "#%02x%02x%02x" % (red, green, blue)


def get_color(color_table: list[tuple[int, int, int]], index: int) -> str:
    if 0 <= index < len(color_table):
        return color_to_string(color_table[index])
    else:
        return "INVALID"


def color_table_to_string(color_table: list[tuple[int, int, int]]) -> str:
    colors = []
    for color in color_table:
        colors.append(color_to_string(color))
    return ", ".join(colors)


def get_disposal_method_string(disposal_method: int) -> str:
    if disposal_method == 0:
        return "none"
    elif disposal_method == 1:
        return "keep"
    elif disposal_method == 2:
        return "restore background"
    elif disposal_method == 3:
        return "restore previous"
    else:
        return str(disposal_method)


print("Version: %s" % str(r.version))
print("Size: %dx%d pixels" % (r.width, r.height))
print("Original Depth: %d bits" % r.original_depth)
if r.pixel_aspect_ratio != 0:
    print("Pixel Aspect Ratio: %d" % r.pixel_aspect_ratio)
if len(r.color_table) > 0:
    description = "%d" % len(r.color_table)
    if r.color_table_sorted:
        description += ", sorted"
    print("Colors (%s): %s" % (description, color_table_to_string(r.color_table)))
    print(
        "Background Color: %s (%d)"
        % (get_color(r.color_table, r.background_color), r.background_color)
    )

for block in r.blocks:
    if isinstance(block, gif.Image):
        print("Image:")
        if (block.left, block.top) != (0, 0):
            print("  Position: %d,%d" % (block.left, block.top))
        print("  Size: %dx%d" % (block.width, block.height))
        if len(block.color_table) > 0:
            description = "%d" % len(block.color_table)
            if block.color_table_sorted:
                description += ", sorted"
            print(
                "  Colors (%s): %s"
                % (description, color_table_to_string(block.color_table))
            )
        decoder = block.decode_lzw()
        clear_count = 0
        for code in decoder.codes[1:]:
            if code == decoder.clear_code:
                clear_count += 1
        description = "%d" % len(decoder.values)
        description += ", code-size=%d" % (block.lzw_min_code_size)
        if block.interlace:
            description += ", interlace"
        if clear_count > 0:
            description += ", n-clears=%d" % clear_count
        if len(decoder.codes) > 0 and decoder.codes[0] != decoder.clear_code:
            description += ", no-clear-at-start"
        if len(decoder.codes) > 0 and decoder.codes[-1] != decoder.eoi_code:
            description += ", no-end-of-information"
        print("  Pixels (%s): %s" % (description, decoder.values))
        lzw_data = block.get_lzw_data()
        if decoder.n_used < len(lzw_data):
            extra_data = lzw_data[decoder.n_used :]
            print("  Unused data (%d): %s" % (len(extra_data), repr(extra_data)))

    elif isinstance(block, gif.PlainTextExtension):
        print("Plain Text Extension:")
        print("  Position: %d,%d" % (block.left, block.top))
        print("  Grid Size: %dx%d" % (block.width, block.height))
        print("  Cell Size: %dx%d pixels" % (block.cell_width, block.cell_height))
        print(
            "  Foreground Color: %s (%d)"
            % (get_color(r.color_table, block.foreground_color), block.foreground_color)
        )
        print(
            "  Background Color: %s (%d)"
            % (get_color(r.color_table, block.background_color), block.background_color)
        )
        print("  Text: %s" % repr(block.get_text()))

    elif isinstance(block, gif.GraphicControlExtension):
        print("Graphic Control Extension:")
        print("  Delay Time: %d/100 ms" % block.delay_time)
        if block.has_transparent:
            print("  Transparent Color: %d" % block.transparent_color)
        elif block.transparent_color != 0:
            print("  Transparent Color: %d (!)" % block.transparent_color)
        print(
            "  Disposal Method: %s" % get_disposal_method_string(block.disposal_method)
        )
        print("  User Input: %s" % repr(block.user_input))

    elif isinstance(block, gif.CommentExtension):
        print("Comment Extension:")
        print("  Comment: %s" % repr(block.get_comment()))

    elif isinstance(block, gif.NetscapeExtension):
        print("Netscape Extension:")
        if block.loop_count is not None:
            print("  Loop Count: %d" % block.loop_count)
        if block.buffer_size is not None:
            print("  Buffer Size: %d" % block.buffer_size)
        for id, data in block.unused_subblocks:
            print("  Sub-Block %d: %s" % (id, repr(data)))

    elif isinstance(block, gif.AnimationExtension):
        print("Animation Extension:")
        if block.loop_count is not None:
            print("  Loop Count: %d" % block.loop_count)
        if block.buffer_size is not None:
            print("  Buffer Size: %d" % block.buffer_size)
        for id, data in block.unused_subblocks:
            print("  Sub-Block %d: %s" % (id, repr(data)))

    elif isinstance(block, gif.XMPDataExtension):
        print("XMP Data Extension:")
        print("  Metadata: %s" % repr(block.get_metadata()))

    elif isinstance(block, gif.ICCColorProfileExtension):
        print("ICC Color Profile Extension:")
        print("  ICC Profile: %s" % repr(block.get_icc_profile()))

    elif isinstance(block, gif.ApplicationExtension):
        print("Application Extension:")
        print("  Application Identifier: %s" % repr(block.identifier))
        print("  Application Authentication Code: %s" % repr(block.authentication_code))
        for block in block.get_application_data():
            print("  Data: %s" % repr(block))

    elif isinstance(block, gif.Extension):
        print("Extension %d:" % block.label)
        for subblock in block.get_subblocks():
            print("  Data: %s" % repr(subblock))

    elif isinstance(block, gif.Trailer):
        pass

    else:
        print("Unknown Block:")
        print("  Data (%d): %s" % (block.length, repr(block.get_data())))

if not r.is_complete():
    print("No trailer")
