#!/usr/bin/python3
""" This thing rasterizes text for use later """

# pylint: disable=wrong-import-position,too-many-locals,unused-argument
# pylint: disable=invalid-name,too-many-instance-attributes

"""
SPDX-License-Identifier: LGPL-2.1+
"""


import os
import sys
import gettext
import math
import cairo
import gi
gi.require_version('Pango', '1.0')
gi.require_version('PangoCairo', '1.0')
from gi.repository import Pango, PangoCairo
from PIL import Image

def usage(return_code):
    """ print usage and exit with the supplied return code """
    if return_code == 0:
        out = sys.stdout
    else:
        out = sys.stderr
    out.write("usage: make-images <label text> <mo file directory> <LINGUAS> <installdir>")
    sys.exit(return_code)

class Rasterizer:
    """ Rasterize some text """

    def __init__(self, label, modir, linguas):
        self.text = label
        self.modir = modir
        while modir.endswith('/'):
            modir = modir[:-1]
        self.linguas = linguas
        self.directory = modir
        self.domain = "fwupd"
        self.font_face = "sans-serif"
        self.pattern = "{directory}/{language}/LC_IMAGES/fwupd-{width}-{height}.{suffix}"

        gettext.textdomain(self.domain)
        gettext.bind_textdomain_codeset(self.domain, 'UTF8')
        gettext.install(self.domain, self.modir)

    @property
    def languages(self):
        """ Find all of our languages """
        for x in open(self.linguas, "r").readlines():
            x = x.strip()
            # currently ligatures seem completely broken in hi, and I don't know
            # why.  They get LANG=C.
            if x == 'hi':
                continue
            yield x
        yield "en"

    def render(self):
        """ Do the work... """
        def render_one(language, string, width, height, filename):
            """ Do the work... """

            font_desc = "Sans %fpx" % (height / 32,)
            fd = Pango.FontDescription(font_desc)
            font_option = cairo.FontOptions()
            font_option.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
            l = Pango.Language.from_string(language)

            img = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)
            cctx = cairo.Context(img)
            layout = PangoCairo.create_layout(cctx)
            pctx = layout.get_context()
            pctx.set_font_description(fd)
            pctx.set_language(l)
            fs = pctx.load_fontset(fd, l)
            PangoCairo.context_set_font_options(pctx, font_option)

            attrs = Pango.AttrList()
            length = len(bytes(string, "utf8"))
            items = Pango.itemize(pctx, string, 0, length, attrs, None)
            gs = Pango.GlyphString()
            Pango.shape(string, length, items[0].analysis, gs)
            del img, cctx, pctx, layout

            def find_size(fs, f, data):
                """ find our size, I hope... """
                (ink, log) = gs.extents(f)
                if ink.height == 0 or ink.width == 0:
                    return False
                data.update({"log": log, "ink": ink})
                return True
            data = {}
            fs.foreach(find_size, data)

            if len(data) == 0:
                print("Missing sans fonts")
                sys.exit(2)
            log = data['log']
            ink = data['ink']

            height = math.ceil(max(ink.height, log.height) / Pango.SCALE)
            width = math.ceil(max(ink.width, log.width) / Pango.SCALE)

            x = -math.ceil(log.x / Pango.SCALE)
            y = -math.ceil(log.y / Pango.SCALE)

            img = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
            cctx = cairo.Context(img)
            layout = PangoCairo.create_layout(cctx)
            pctx = layout.get_context()
            PangoCairo.context_set_font_options(pctx, font_option)

            cctx.set_source_rgb(1, 1, 1)
            cctx.move_to(x, y)
            def do_write(fs, f, data):
                """ write out glyphs """
                ink = gs.extents(f)[0]
                if ink.height == 0 or ink.width == 0:
                    return False
                PangoCairo.show_glyph_string(cctx, f, gs)
                return True
            fs.foreach(do_write, None)
            img.flush()
            try:
                tmpname = filename[len(os.environ['DESTDIR']):]
            except KeyError:
                tmpname = filename[len(os.environ['MESON_BUILD_ROOT']):]
            print("Writing %s                    " % (tmpname,), end='\r')
            def make_dir(d):
                """ make our parent dir and then our own dir """
                if os.access(d, os.O_RDWR):
                    return
                parts = os.path.split(d)
                if parts and parts[0]:
                    make_dir(parts[0])
                os.mkdir(d, 0o755)
            d = os.path.split(filename)[0]
            make_dir(d)
            img.write_to_png(filename)
            pimg = Image.open(filename)
            img = pimg.copy()
            del pimg
            img.save(filename)

        for lang in self.languages:
            #print("lang:\"%s\" string:\"%s\"" % (lang, string))
            # these are the 1.6:1 of some common(ish) screen widths
            sizes = ((640, 480), (800, 600), (1024, 768), (1920, 1080),
                     (3840, 2160), (5120, 2880), (5688, 3200), (7680, 4320))
            nameinfo = {
                'directory': self.directory,
                'language': lang,
            }
            if lang == 'en':
                string = self.text
            else:
                tl = gettext.translation(self.domain, self.modir,
                                         languages=[lang])
                string = tl.gettext(self.text)
                if string == self.text:
                    continue
            for width, height in sizes:
                nameinfo.update({'width': width,
                                 'height': height,
                                 'suffix': 'bmp'})
                filename = self.pattern.format_map(nameinfo)
                render_one(lang, string, width, height, filename)
        print("")

if __name__ == '__main__':
    if {'-?', '--help', '--usage'}.intersection(set(sys.argv)):
        usage(0)
    if len(sys.argv) != 4:
        usage(1)

    label = os.fsencode(sys.argv[1]).decode('utf-8')
    r = Rasterizer(label=label, modir=sys.argv[2],
                   linguas=sys.argv[3])
    r.render()
