#!/usr/bin/env python3
"""Generate replaytitle.s: big chrome "REPLAY" (72x24 px, 9x3 tiles) for the automatic replay.
Open Sans Condensed ExtraBold Italic, 1 px black outline, silver bands like the NHL'94 logo,
in-game palette 0 greys (1 = $1FF, 3 = $1B6, 5 = $16D, 6 = $0DB, 7 = $092, $E = $049, 4 = black).
Usage: replaytitle.py [preview.png]"""
import sys, os
from PIL import Image, ImageDraw, ImageFont, ImageFilter
FONT = '/usr/share/fonts/TTF/OpenSans-CondensedExtraBoldItalic.ttf'
band = [1, 1, 3, 5, 6, 5, 3, 1, 3]                  # palette 0 index per vertical ninth
def render(text, W, H, margin):
    best = None
    for size in range(6, 40):
        f = ImageFont.truetype(FONT, size)
        bb = f.getbbox(text)
        if bb[2] - bb[0] <= W - margin and bb[3] - bb[1] <= H - margin: best = (f, bb)
    f, bb = best
    mask = Image.new('L', (W, H), 0)
    ImageDraw.Draw(mask).text(((W - (bb[2] - bb[0])) // 2 - bb[0], (H - (bb[3] - bb[1])) // 2 - bb[1]), text, font=f, fill=255)
    m = mask.point(lambda v: 255 if v > 110 else 0)
    outline = m.filter(ImageFilter.MaxFilter(3))
    mp, op = m.load(), outline.load()
    ys = [y for y in range(H) for x in range(W) if mp[x, y]]
    top, bot = min(ys), max(ys)
    pix = [[0] * W for _ in range(H)]
    for y in range(H):
        for x in range(W):
            if mp[x, y]: pix[y][x] = band[min(8, int((y - top) / max(1, bot - top) * 9))]
            elif op[x, y]: pix[y][x] = 4
    tiles = []
    for ty in range(H // 8):
        for tx in range(W // 8):
            for y in range(8):
                row = pix[ty * 8 + y][tx * 8:tx * 8 + 8]
                tiles.append(sum(v << (28 - 4 * i) for i, v in enumerate(row)))
    return pix, tiles
here = os.path.dirname(os.path.abspath(__file__))
src = open(os.path.join(here, 'replaytitle.s')).read()
def put(src, label, tiles):
    a = src.index(label + ':\n'); b = src.index('| end of ' + label)
    return src[:a] + label + ':\n' + ''.join('    .long ' + ','.join('0x%08X' % v for v in tiles[i:i + 8]) + '\n' for i in range(0, len(tiles), 8)) + src[b:]
pix, tiles = render('REPLAY', 72, 24, 4)           # 9 x 3 tiles
# r28 (jdc): the hint in the score box's style - black plate, grey bevel frame, light grey
# blocky 6x7 letters (palette 0: 5 = $16D frame, 6 = $0DB inner frame, 4 black, 3 = $1B6 text).
BOX = {
 'X': ["##..##", "##..##", ".####.", "..##..", ".####.", "##..##", "##..##"],
 '+': ["......", "..##..", "..##..", "######", "..##..", "..##..", "......"],
 'B': ["#####.", "##..##", "##..##", "#####.", "##..##", "##..##", "#####."],
 'S': [".####.", "##..##", "##....", ".####.", "....##", "##..##", ".####."],
 'K': ["##..##", "##.##.", "####..", "###...", "####..", "##.##.", "##..##"],
 'I': ["######", "..##..", "..##..", "..##..", "..##..", "..##..", "######"],
 'P': ["#####.", "##..##", "##..##", "#####.", "##....", "##....", "##...."],
}
def boxhint(text, W, H):
    pix = [[4] * W for _ in range(H)]
    for x in range(W): pix[0][x] = pix[H - 1][x] = 5
    for y in range(H): pix[y][0] = pix[y][W - 1] = 5
    for x in range(1, W - 1): pix[1][x] = pix[H - 2][x] = 6
    for y in range(1, H - 1): pix[y][1] = pix[y][W - 2] = 6
    width = sum(3 if c == ' ' else 7 for c in text) - 1
    x0 = (W - width) // 2; y0 = (H - 7) // 2
    for c in text:
        if c == ' ': x0 += 3; continue
        for y, row in enumerate(BOX[c]):
            for x, v in enumerate(row):
                if v == '#': pix[y0 + y][x0 + x] = 3
        x0 += 7
    tiles = []
    for ty in range(H // 8):
        for tx in range(W // 8):
            for y in range(8):
                tiles.append(sum(v << (28 - 4 * i) for i, v in enumerate(pix[ty * 8 + y][tx * 8:tx * 8 + 8])))
    return pix, tiles
hpix, hint = boxhint('X+B SKIP', 56, 16)           # 7 x 2 tiles (pad A + C = Xbox X + B)
src = put(put(src, 'title', tiles), 'hint', hint)
open(os.path.join(here, 'replaytitle.s'), 'w').write(src)
if len(sys.argv) > 1:
    rgb = {0: (0, 170, 170), 1: (255, 255, 255), 3: (219, 219, 219), 5: (182, 182, 182), 6: (109, 109, 109), 4: (0, 0, 0), 7: (73, 73, 73)}
    im = Image.new('RGB', (72, 40), (0, 170, 170)); im.putdata([rgb[(pix + hpix and (pix[y][x] if y < 24 else (hpix[y - 24][x] if x < 56 else 0)))] for y in range(40) for x in range(72)])
    im.resize((72 * 6, 40 * 6), Image.NEAREST).save(sys.argv[1])
print('replaytitle.s:', len(tiles) // 8, '+', len(hint) // 8, 'tiles')
