#!/usr/bin/env python3


# Copyright 2018 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

'''
Regenerate markdown docs by using `meson.py` from the root dir
'''

import argparse
import os
import re
import subprocess
import sys
import textwrap
import typing as T
from pathlib import Path

PathLike = T.Union[Path,str]

def _get_meson_output(root_dir: Path, args: T.List) -> str:
    env = os.environ.copy()
    env['COLUMNS'] = '80'
    return subprocess.run([str(sys.executable), str(root_dir/'meson.py')] + args, check=True, capture_output=True, text=True, env=env).stdout.strip()

def get_commands_data(root_dir: Path) -> T.Dict[str, T.Any]:
    usage_start_pattern = re.compile(r'^usage: ', re.MULTILINE)
    positional_start_pattern = re.compile(r'^positional arguments:[\t ]*[\r\n]+', re.MULTILINE)
    options_start_pattern = re.compile(r'^optional arguments:[\t ]*[\r\n]+', re.MULTILINE)
    commands_start_pattern = re.compile(r'^[A-Za-z ]*[Cc]ommands:[\t ]*[\r\n]+', re.MULTILINE)

    def get_next_start(iterators: T.Sequence[T.Any], end: T.Optional[int]) -> int:
        return next((i.start() for i in iterators if i), end)

    def normalize_text(text: str) -> str:
        # clean up formatting
        out = text
        out = re.sub(r'\r\n', r'\r', out, flags=re.MULTILINE) # replace newlines with a linux EOL
        out = re.sub(r'^ +$', '', out, flags=re.MULTILINE) # remove trailing whitespace
        out = re.sub(r'(?:^\n+|\n+$)', '', out) # remove trailing empty lines
        return out

    def parse_cmd(cmd: str) -> T.Dict[str, str]:
        cmd_len = len(cmd)
        usage = usage_start_pattern.search(cmd)
        positionals = positional_start_pattern.search(cmd)
        options = options_start_pattern.search(cmd)
        commands = commands_start_pattern.search(cmd)

        arguments_start = get_next_start([positionals, options, commands], None)
        assert arguments_start

        # replace `usage:` with `$` and dedent
        dedent_size = (usage.end() - usage.start()) - len('$ ')
        usage_text = textwrap.dedent(f'{dedent_size * " "}$ {normalize_text(cmd[usage.end():arguments_start])}')

        return {
            'usage': usage_text,
            'arguments': normalize_text(cmd[arguments_start:cmd_len]),
        }

    def clean_dir_arguments(text: str) -> str:
        # Remove platform specific defaults
        args = [
            'prefix',
            'bindir',
            'datadir',
            'includedir',
            'infodir',
            'libdir',
            'libexecdir',
            'localedir',
            'localstatedir',
            'mandir',
            'sbindir',
            'sharedstatedir',
            'sysconfdir'
        ]
        out = text
        for a in args:
            out = re.sub(r'(--' + a + r' .+?)\s+\(default:.+?\)(\.)?', r'\1\2', out, flags=re.MULTILINE|re.DOTALL)
        return out

    output = _get_meson_output(root_dir, ['--help'])
    commands = {c.strip() for c in re.findall(r'usage:(?:.+)?{((?:[a-z]+,*)+?)}', output, re.MULTILINE|re.DOTALL)[0].split(',')}
    commands.remove('help')

    cmd_data = dict()

    for cmd in commands:
        cmd_output = _get_meson_output(root_dir, [cmd, '--help'])
        cmd_data[cmd] = parse_cmd(cmd_output)
        if cmd in ['setup', 'configure']:
            cmd_data[cmd]['arguments'] = clean_dir_arguments(cmd_data[cmd]['arguments'])

    return cmd_data

def generate_hotdoc_includes(root_dir: Path, output_dir: Path) -> None:
    cmd_data = get_commands_data(root_dir)

    for cmd, parsed in cmd_data.items():
        for typ in parsed.keys():
            with open(output_dir / (cmd+'_'+typ+'.inc'), 'w') as f:
                f.write(parsed[typ])

def regenerate_docs(output_dir: PathLike,
                    dummy_output_file: T.Optional[PathLike]) -> None:
    if not output_dir:
        raise ValueError(f'Output directory value is not set')

    output_dir = Path(output_dir).resolve()
    output_dir.mkdir(parents=True, exist_ok=True)

    root_dir = Path(__file__).resolve().parent.parent

    generate_hotdoc_includes(root_dir, output_dir)

    if dummy_output_file:
        with open(output_dir/dummy_output_file, 'w') as f:
            f.write('dummy file for custom_target output')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Generate meson docs')
    parser.add_argument('--output-dir', required=True)
    parser.add_argument('--dummy-output-file', type=str)

    args = parser.parse_args()

    regenerate_docs(output_dir=args.output_dir,
                    dummy_output_file=args.dummy_output_file)
