from .ReadHelper import read_int_32le, read_int_16le, read_int_8, read_int_24be, signed8


def read_zhs_stitches(f, out):
    count = 0

    xx = 0
    yy = 0
    while True:
        count += 1
        b = bytearray(f.read(3))
        if len(b) != 3:
            break
        ctrl = b[0]
        if ctrl == 0x10:
            # Checksum
            continue
        # x
        x = 0
        x += b[1] & 0b00000001
        x += b[2] & 0b00000010
        x += b[1] & 0b00000100
        x += b[2] & 0b00001000
        x += b[1] & 0b00010000
        x += b[2] & 0b00100000
        x += b[1] & 0b01000000
        x += b[2] & 0b10000000
        x = signed8(x)
        if x >= 63:
            x += 1
        if x <= -63:
            x -= 1

        # y
        y = 0
        y += b[2] & 0b00000001
        y += b[1] & 0b00000010
        y += b[2] & 0b00000100
        y += b[1] & 0b00001000
        y += b[2] & 0b00010000
        y += b[1] & 0b00100000
        y += b[2] & 0b01000000
        y += b[1] & 0b10000000

        y = signed8(y)
        if y >= 63:
            y += 1
        if y <= -63:
            y -= 1

        xx += x
        yy += y
        if ctrl == 0x41:
            # Still unmapped.
            pass
        elif ctrl == 0x02:
            out.stitch(xx, -yy)
            xx = 0
            yy = 0
            continue
        elif ctrl == 0x01:
            out.move(xx, -yy)
            xx = 0
            yy = 0
            continue
        elif ctrl == 0x04:
            xx = 0
            yy = 0
            out.color_change()
            continue
        elif ctrl == 0x80:
            break
    out.end()


def read_zhs_header(f, out):
    color_count = read_int_8(f)
    for i in range(color_count):
        out.add_thread(read_int_24be(f))
    length = read_int_16le(f)
    b = bytearray(f.read(length))
    thread_data = b.decode('utf8')
    threads = thread_data.split("&$")
    try:
        for i, data in enumerate(threads[1:]):
            thread = out.threadlist[i]
            parts = data.split("&#")
            try:
                if len(parts[0]):
                    thread.chart = parts[0]
                if len(parts[1]):
                    thread.description = parts[1]
                if len(parts[2]) > 3:
                    thread.catalog_number = parts[2][:-2]
            except IndexError:
                pass
    except IndexError:
        pass


def read(f, out, settings=None):
    f.seek(0x0F, 0)
    stitch_start_position = read_int_32le(f)
    header_start_position = read_int_32le(f)
    f.seek(header_start_position, 0)
    read_zhs_header(f, out)
    f.seek(stitch_start_position, 0)
    read_zhs_stitches(f, out)
