#!/usr/bin/env python3
"""Rescale the premium notification dialogs (geometry, borders, animations, fonts).

Designed for a proportional rescale of the premium style XMLs,
e.g. 0.75 = 75 % of the original 838x386 design.

Usage:
    python3 rescale_premium.py 0.75
"""
import os
import re
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
ADDON = os.path.abspath(os.path.join(HERE, '..', '..'))
PREMIUM_DIR = os.path.join(ADDON, 'resources', 'skins', 'Default', '1080i', 'notifications', 'premium')

FONT_MAP = {
    'font45_title': 'font32_title',
    'font36_title': 'font25_title',
    'font37': 'font27',
    'font14': 'font12',
    'font13': 'font12',
    'font32': 'font12',
    'font27': 'font10',
}


def scale_int(value, factor):
    return int(round(value * factor))


def scale_geometry(text, factor):
    def geo(match):
        tag, value = match.group(1), int(match.group(2))
        return f'<{tag}>{scale_int(value, factor)}</{tag}>'

    return re.sub(r'<(left|top|width|height)>(\d+)</\1>', geo, text)


def scale_borders(text, factor):
    return re.sub(r'border="(\d+)"', lambda m: f'border="{scale_int(int(m.group(1)), factor)}"', text)


def scale_animations(text, factor):
    def anim(match):
        attr, value = match.group(1), match.group(2)
        parts = [str(scale_int(int(part), factor)) for part in value.split(',')]
        return f'{attr}="{",".join(parts)}"'

    return re.sub(r'\b(start|end)="(-?\d+(?:,-?\d+)*)"', anim, text)


def swap_fonts(text):
    return re.sub(r'<font>([a-zA-Z0-9_]+)</font>', lambda m: f'<font>{FONT_MAP.get(m.group(1), m.group(1))}</font>', text)


def restore_window_origin(text):
    return re.sub(r'<left>\d+</left>\n(\s*)<top>\d+</top>', r'<left>50</left>\n\1<top>50</top>', text, count=1)


def transform(text, factor):
    # Protect the countdown progress bar: keep its native texture size and borders.
    progress_blocks = []

    def protect(match):
        progress_blocks.append(match.group(0))
        return f'<!--PROGRESS{len(progress_blocks) - 1}-->'

    text = re.sub(r'<control type="progress".*?</control>', protect, text, flags=re.S)

    text = scale_geometry(text, factor)
    text = scale_borders(text, factor)
    text = scale_animations(text, factor)
    text = swap_fonts(text)
    text = restore_window_origin(text)

    for index, block in enumerate(progress_blocks):
        block = re.sub(r'<(left|top|width)>(\d+)</\1>',
                       lambda m: f'<{m.group(1)}>{scale_int(int(m.group(2)), factor)}</{m.group(1)}>',
                       block)
        text = text.replace(f'<!--PROGRESS{index}-->', block)

    return text


def main():
    if len(sys.argv) < 2:
        print(__doc__)
        return 1
    factor = float(sys.argv[1])

    files = [
        ('DialogEpisodeInfoWithGame.xml', '111', '110'),
        ('DialogMovieInfoWithGame.xml', '111', '110'),
        ('DialogAutoplayCountdown.xml', None, None),
    ]
    for name, old_default, new_default in files:
        path = os.path.join(PREMIUM_DIR, name)
        with open(path, encoding='utf-8') as fh:
            text = fh.read()
        text = transform(text, factor)
        if old_default:
            text = text.replace(f'<defaultcontrol always="true">{old_default}</defaultcontrol>',
                                f'<defaultcontrol always="true">{new_default}</defaultcontrol>')
        with open(path, 'w', encoding='utf-8') as fh:
            fh.write(text)
        print(f"rescaled {name} by {factor}")
    return 0


if __name__ == '__main__':
    sys.exit(main())
