#!/usr/bin/env python3

import shutil
import textwrap
import subprocess
import sys
import fnmatch
import warnings
import filecmp
from pathlib import Path

import click

FILENAME_PATTERNS = ['*.svg', '*.png', '*.jpg', '*.pdf', '*.eps']


def git(*args, repo=None):
    cmd = ['git']
    if repo:
        cmd += ['-C', str(repo)]
    proc = subprocess.run([*cmd, *args], check=True, capture_output=True, text=True)
    return proc.stdout + proc.stderr

def remote_url(repo=None):
    branch = 'unknown'
    try:
        branch = git('branch', '--show-current', repo=repo).strip()
        remote = git('config', f'branch.{branch}.remote', repo=repo).strip()
    except subprocess.CalledProcessError:
        warnings.warn(f'Cannot identify git remote for branch {branch} in repo {repo or "<this repo>"}, using first remote')
        
        remote = git('remote', repo=repo).strip().splitlines()[0].strip()
        if not remote:
            raise SystemError(f'Repo {repo or "<this repo>"} has no remotes configured.')

    return git('remote', 'get-url', remote, repo=repo).strip()

def paths(s):
    return [Path(line.strip()) for line in s.strip().splitlines()]

def tex_escape(s):
    s = str(s)
    s = s.replace('_', r'\_')
    return s


@click.command()
@click.argument('figure_dir', default='.', type=click.Path(exists=True, file_okay=False, path_type=Path))
def cli(figure_dir):
    figure_dir = figure_dir.resolve()
    figure_files = set(fn.name for fn in figure_dir.iterdir()
               if fn.is_file() and any(fnmatch.fnmatch(fn.name.lower(), pat) for pat in FILENAME_PATTERNS))

    submodules = [p for p in paths(git('submodule', 'foreach', '--quiet', 'pwd'))
                  if p.parent == figure_dir]

    repo_matches = {}
    for mod in submodules:
        for fn in paths(git('ls-tree', '-r', 'HEAD', '--name-only', '--full-tree', repo=mod)):
            if fn.name in figure_files:
                if fn.name in repo_matches:
                    prev_mod, prev_fn = repo_matches[fn.name]
                    warnings.warn(f'Ambiguous match for {fn.name}: found {mod / fn} in addition to previous match of {prev_mod / prev_fn}.')
                else:
                    repo_matches[fn.name] = (mod, fn)

    meta_file = lambda suffix: figure_dir / (fig_fn + suffix)

    for fig_fn, (mod, mod_fn) in repo_matches.items():
        fig_file = figure_dir / fig_fn
        mod_file = mod / mod_fn
        scale = ""
        if filecmp.cmp(fig_file, mod_file):
            print(f'{fig_fn} is up to date, updating metadata.')
        else:
            shutil.copy(mod_file, fig_file)
            if fig_file.suffix.lower() in ('.png', '.jpg'):
                subprocess.run(['magick', fig_file,
                                '-resize', '1000x1000>',
                                figure_dir / f'scaled-{fig_file.name}'],
                               check=True)
                scale = "scaled down for preview"
                print(f'Scaled {fig_fn} for preview')

            elif fig_file.suffix.lower() == '.svg':
                subprocess.run(['inkscape', f'--export-filename={fig_file.with_suffix(".eps")}', fig_file],
                               check=True)
                print(f'Rendered {fig_fn} to EPS')

            print(f'Updated {fig_fn} from {mod_fn}.')

        repo_url = remote_url(repo=mod)

        url_prefix = repo_url.replace('git@git.jaseg.de:', 'https://git.jaseg.de/')
        repo_name = repo_url.replace('git@git.jaseg.de:', '').replace('https://git.jaseg.de/', '')
        git_rev = git('rev-parse', 'HEAD', repo=mod).strip()
        cgit_url = f'{url_prefix}/plain/{mod_fn}?h={git_rev}'

        git_tag = git('describe', '--always', '--tags', repo=mod).strip()

        state = r'\camerareadygraphics' if 'camera-ready' in fig_fn or 'final' in fig_fn else r'\draftgraphics'
        meta_file('.latex_meta').write_text(textwrap.dedent(fr'''
                \def\resourcestate{{{state}}}
                \def\resourcescale{{{scale}}}
                \def\resourceurl{{{tex_escape(cgit_url)}}}
                \def\resourcerev{{{tex_escape(git_tag)}}}
                \def\resourcerepo{{{tex_escape(repo_name)}}}
                \def\resourcepath{{{tex_escape(mod_fn)}}}
            ''').strip())

    unmatched = figure_files - set(repo_matches.keys())
    if unmatched:
        print()
        print('Unmatched files:', file=sys.stderr)
        for fn in unmatched:
            print(fn, file=sys.stderr)

if __name__ == '__main__':
    cli()
