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(face, words, advance, target_advance):
    font = hb.font_create(face)
    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(face, words):
    font = hb.font_create(face)
    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(face, text, target_advance):
    lines = []
    words = []
    for word in text.split():
        words.append(word)
        buf, advance = shape(face, words)
        if advance > target_advance:
            # Shrink
            ret, buf, variation = justify(face, 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(face, 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(face, 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(face, 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="font file")
    parser.add_argument("textfile", help="text")
    args = parser.parse_args()
    main(args.fontfile, args.textfile)
