import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, HarfBuzz as hb


POOL = {}


def move_to_f(funcs, draw_data, st, to_x, to_y, user_data):
    context = POOL[draw_data]
    context.move_to(to_x, to_y)


def line_to_f(funcs, draw_data, st, to_x, to_y, user_data):
    context = POOL[draw_data]
    context.line_to(to_x, to_y)


def cubic_to_f(
    funcs,
    draw_data,
    st,
    control1_x,
    control1_y,
    control2_x,
    control2_y,
    to_x,
    to_y,
    user_data,
):
    context = POOL[draw_data]
    context.curve_to(control1_x, control1_y, control2_x, control2_y, to_x, to_y)


def close_path_f(funcs, draw_data, st, user_data):
    context = POOL[draw_data]
    context.close_path()


DFUNCS = hb.draw_funcs_create()
hb.draw_funcs_set_move_to_func(DFUNCS, move_to_f, None)
hb.draw_funcs_set_line_to_func(DFUNCS, line_to_f, None)
hb.draw_funcs_set_cubic_to_func(DFUNCS, cubic_to_f, None)
hb.draw_funcs_set_close_path_func(DFUNCS, close_path_f, None)


def push_transform_f(funcs, paint_data, xx, yx, xy, yy, dx, dy, user_data):
    raise NotImplementedError


def pop_transform_f(funcs, paint_data, user_data):
    raise NotImplementedError


def color_f(funcs, paint_data, is_foreground, color, user_data):
    context = POOL[paint_data]
    r = hb.color_get_red(color) / 255
    g = hb.color_get_green(color) / 255
    b = hb.color_get_blue(color) / 255
    a = hb.color_get_alpha(color) / 255
    context.set_source_rgba(r, g, b, a)
    context.paint()


def push_clip_rectangle_f(funcs, paint_data, xmin, ymin, xmax, ymax, user_data):
    context = POOL[paint_data]
    context.save()
    context.rectangle(xmin, ymin, xmax, ymax)
    context.clip()


def push_clip_glyph_f(funcs, paint_data, glyph, font, user_data):
    context = POOL[paint_data]
    context.save()
    context.new_path()
    hb.font_draw_glyph(font, glyph, DFUNCS, paint_data)
    context.close_path()
    context.clip()


def pop_clip_f(funcs, paint_data, user_data):
    context = POOL[paint_data]
    context.restore()


def push_group_f(funcs, paint_data, user_data):
    raise NotImplementedError


def pop_group_f(funcs, paint_data, mode, user_data):
    raise NotImplementedError


PFUNCS = hb.paint_funcs_create()
hb.paint_funcs_set_push_transform_func(PFUNCS, push_transform_f, None)
hb.paint_funcs_set_pop_transform_func(PFUNCS, pop_transform_f, None)
hb.paint_funcs_set_color_func(PFUNCS, color_f, None)
hb.paint_funcs_set_push_clip_glyph_func(PFUNCS, push_clip_glyph_f, None)
hb.paint_funcs_set_push_clip_rectangle_func(PFUNCS, push_clip_rectangle_f, None)
hb.paint_funcs_set_pop_clip_func(PFUNCS, pop_clip_f, None)
hb.paint_funcs_set_push_group_func(PFUNCS, push_group_f, None)
hb.paint_funcs_set_pop_group_func(PFUNCS, pop_group_f, None)


def makebuffer(words):
    buf = hb.buffer_create()

    text = " ".join(words)
    hb.buffer_add_codepoints(buf, [ord(c) for c in text], 0, len(text))

    hb.buffer_guess_segment_properties(buf)

    return buf


def justify(font, words, advance, target_advance):
    buf = makebuffer(words)

    wiggle = 5
    shrink = target_advance - wiggle < advance
    expand = target_advance + wiggle > advance

    ret, advance, tag, value = hb.shape_justify(
        font,
        buf,
        None,
        None,
        target_advance,
        target_advance,
        advance,
    )

    if not ret:
        return False, buf, None

    if tag:
        variation = hb.variation_t()
        variation.tag = tag
        variation.value = value
    else:
        variation = None

    if shrink and advance > target_advance + wiggle:
        return False, buf, variation
    if expand and advance < target_advance - wiggle:
        return False, buf, variation

    return True, buf, variation


def shape(font, words):
    buf = makebuffer(words)
    hb.shape(font, buf)
    positions = hb.buffer_get_glyph_positions(buf)
    advance = sum(p.x_advance for p in positions)
    return buf, advance


def typeset(font, text, target_advance):
    lines = []
    words = []
    for word in text.split():
        words.append(word)
        buf, advance = shape(font, words)
        if advance > target_advance:
            # Shrink
            ret, buf, variation = justify(font, words, advance, target_advance)
            if ret:
                lines.append((buf, variation))
                words = []
            # If if fails, pop the last word and shrink, and hope for the best.
            # A too short line is better than too long.
            elif len(words) > 1:
                words.pop()
                _, buf, variation = justify(font, words, advance, target_advance)
                lines.append((buf, variation))
                words = [word]
            # But if it is one word, meh.
            else:
                lines.append((buf, variation))
                words = []

    # Justify last line
    if words:
        _, buf, variation = justify(font, words, advance, target_advance)
        lines.append((buf, variation))

    return lines


def render(face, text, context, width, height, fontsize):
    font = hb.font_create(face)

    margin = fontsize * 2
    scale = fontsize / hb.face_get_upem(face)
    target_advance = (width - (margin * 2)) / scale

    lines = typeset(font, text, target_advance)

    _, extents = hb.font_get_h_extents(font)
    lineheight = extents.ascender - extents.descender + extents.line_gap
    lineheight *= scale

    context.save()
    context.translate(0, margin)
    context.set_font_size(12)
    context.set_source_rgb(1, 0, 0)
    for buf, variation in lines:
        rtl = hb.buffer_get_direction(buf) == hb.direction_t.RTL
        if rtl:
            hb.buffer_reverse(buf)
        infos = hb.buffer_get_glyph_infos(buf)
        positions = hb.buffer_get_glyph_positions(buf)
        advance = sum(p.x_advance for p in positions)

        context.translate(0, lineheight)
        context.save()

        context.save()
        context.move_to(0, -20)
        if variation:
            tag = hb.tag_to_string(variation.tag).decode("ascii")
            context.show_text(f" {tag}={variation.value:g}")
        context.move_to(0, 0)
        context.show_text(f" {advance:g}/{target_advance:g}")
        context.restore()

        if variation:
            hb.font_set_variations(font, [variation])

        context.translate(margin, 0)
        context.scale(scale, -scale)

        if rtl:
            context.translate(target_advance, 0)

        for info, pos in zip(infos, positions):
            if rtl:
                context.translate(-pos.x_advance, pos.y_advance)
            context.save()
            context.translate(pos.x_offset, pos.y_offset)
            hb.font_paint_glyph(font, info.codepoint, PFUNCS, id(context), 0, 0x0000FF)
            context.restore()
            if not rtl:
                context.translate(+pos.x_advance, pos.y_advance)

        context.restore()
    context.restore()


def main(fontpath, textpath):
    fontsize = 70

    blob = hb.blob_create_from_file(fontpath)
    face = hb.face_create(blob, 0)

    with open(textpath) as f:
        text = f.read()

    def on_draw(da, context):
        alloc = da.get_allocation()
        POOL[id(context)] = context
        render(face, text, context, alloc.width, alloc.height, fontsize)
        del POOL[id(context)]

    drawingarea = Gtk.DrawingArea()
    drawingarea.connect("draw", on_draw)

    win = Gtk.Window()
    win.connect("destroy", Gtk.main_quit)
    win.set_default_size(1000, 700)
    win.add(drawingarea)

    win.show_all()
    Gtk.main()


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="HarfBuzz justification demo.")
    parser.add_argument("fontfile", help="input Glyphs source file")
    parser.add_argument("textfile", help="font version")
    args = parser.parse_args()
    main(args.fontfile, args.textfile)
