#!/usr/bin/env python3

import sys
from json import dump, loads
from pathlib import Path
from ruamel.yaml import YAML
from ansi2html import Ansi2HTMLConverter
from bs4 import BeautifulSoup

from rougail import Rougail
from rougail.user_data import mandatories
from rougail.config import get_rougail_config
from rougail.output_display import RougailOutputDisplay
from rougail.user_data_yaml import RougailUserDataYaml
from rougail.output_doc import RougailOutputDoc


if __name__ == "__main__":
    builder_dir = sys.argv[1]
    previous = Path(builder_dir) / "previous.yml"
    with Path("install.txt").open() as fh:
        cmd = fh.read()
    commit_id = sys.argv[2]
#    rougailconfig = RougailConfig.copy()
    rougailconfig = get_rougail_config(backward_compatibility=False, add_extra_options=False)
    rougailconfig['main_structural_directories'] = ['firefox']
    if Path('config/namespace').is_file():
        has_namespace = True
        has_foxyproxy = False
    elif Path('foxyproxy').is_dir():
        has_foxyproxy = True
        has_namespace = True
        rougailconfig['main_namespace'] = 'Firefox'
        rougailconfig['extra_namespaces'] = {'FoxyProxy': ['foxyproxy']}
    else:
        has_foxyproxy = False
        has_namespace = False
        rougailconfig['main_namespace'] = None
#    rougailconfig['tiramisu_cache'] = "cache.py"
    if Path('mode').is_file():
        rougailconfig['modes_level'] = ['basic', 'standard', 'advanced']
        has_mode = True
    else:
        has_mode = False
    rougailconfig['step.output'] = 'doc'
    rougail = Rougail(rougailconfig)
    config = rougail.run()
#    print(config.value.get())
    rougailconfig['doc.output_format'] = 'github'
    rougailconfig['doc.title_level'] = 3
    inventory = RougailOutputDoc(config, rougailconfig=rougailconfig)
    inventory.load()
    inventory.load_formatter()
    inv_formatter = inventory.formatter
    rougailconfig['step.output'] = 'display'
    rougailconfig['display.console.max_width'] = 80
    summary = Path('summary_before.md')
    if summary.is_file():
        with summary.open('r') as sfh:
            doc = sfh.read() + '\n\n'
    else:
        doc = ''
    yaml = YAML()
    namespace = 'firefox'
    if rougailconfig['main_namespace']:
        dirname = "foxyproxy"
    else:
        dirname = "firefox"
    doc += inv_formatter.title('Screenshot', 2) + '\n'
    doc += f'<img src="{namespace}.png" width=50% height=50% alt="{namespace.capitalize()} Proxy setting"/>\n\n'
#    with doc_file.open('r') as docfh:
#        doc += docfh.read()
    doc += '\n' + inv_formatter.title('Clone and install', 2) + '\n\n'
    doc += "To test this tutorial, you need to download this repository and install Rougail:\n\n"
    doc += f'```shell\n{cmd}```\n\n'
    doc += "Then switch to the tutorial page:\n\n"
    doc += f"```shell\ngit switch --detach {commit_id}\n```\n"
    tree = Path('tree.html')
    display_yml = None
    if tree.is_file():
        doc += '\n' + inv_formatter.title('Structure', 2) + '\n\n'
        with tree.open() as fh:
            soup = BeautifulSoup(fh.read(), features="lxml")
            tree_content = str(soup.find('p'))
        doc += tree_content + "\n\n"
        with tree.open("w") as fh:
            fh.write(tree_content)
    for f in Path(".").iterdir():
        if f.name.startswith('DISPLAY_'):
            filename = f.name[8:]
            display_yml = Path(dirname) / filename
            break
    else:
        files = list(Path(dirname).iterdir())
        files.sort()
        for f in reversed(files):
            if not f.name.endswith('.yml'):
                continue
            display_yml = f
            break
    if display_yml:
        doc += f"Contents of the {str(display_yml)} file"
        doc += '\n\n```yml\n'
        with display_yml.open(encoding="utf8") as file_fh:
            doc += file_fh.read()
        doc += '\n```\n'
        doc += "\n***\n"
    rougailconfig['step.output'] = 'doc'
    rougailconfig["doc.title_level"] = 4
    inv_doc = inventory.run()[1]
    CMD = "rougail -m firefox/ "
    if has_namespace:
        CMD += "-s Firefox "
    if has_foxyproxy:
        CMD += "-xn FoxyProxy -xd 0 foxyproxy/ "
    if has_mode:
        CMD += "--modes_level basic standard advanced "
    if inv_doc:
        doc += inv_formatter.title("Let's generate the documentation", 3)
        cmd = CMD + "-o doc"
        doc += f'```shell\n{cmd}\n```\n'
        doc += inv_doc
        doc += "\n***\n"
    if previous.is_file():
        rougailconfig["doc.contents"] = ["changelog"]
        rougailconfig["doc.changelog.previous_json_file"] = str(previous)
        inv_doc = inventory.run()[1]
        if inv_doc:
            doc += inv_formatter.title("Let's generate the changelog", 3)
            cmd = CMD + "-o doc --doc.contents changelog"
            doc += f'```shell\n{cmd}\n```\n'
            doc += inv_doc + "\n"
            doc += "***\n"
    # save PREVIOUS
    rougailconfig["doc.contents"] = ["variables"]
    rougailconfig['doc.output_format'] = 'json'
    data = inventory.run()[1]
    if data:
        with previous.open('w') as fh:
            dump(loads(data), fh)
    #
    rougailconfig['step.output'] = 'display'
    config_dir = Path('config')
    if config_dir.is_dir():
        doc += inv_formatter.title('User datas', 2)
        configs = list(config_dir.iterdir())
        configs.sort()
        for idx, dirname in enumerate(configs):
            if dirname.is_file():
                continue
            for filename in dirname.iterdir():
                if filename.name.endswith('.yml') or filename.name.endswith('.yaml'):
                    doc += inv_formatter.title(f'Example {idx + 1}', 3)
                    doc += inv_formatter.title(str(filename), 4)
                    doc += '\n```yml\n'
                    with filename.open(encoding="utf8") as file_fh:
                        doc += file_fh.read()
                    doc += '```\n'
                    doc += "\n***\n"
                    rougail = Rougail(rougailconfig)
                    tiramisu_config = rougail.run()
                    rougailconfig['step.user_data'] = ['yaml']
                    rougailconfig['yaml.filename'] = [str(filename)]
                    data = RougailUserDataYaml(tiramisu_config, rougailconfig=rougailconfig)
                    ret = data.run()
                    errors = rougail.user_data(ret)
                    tiramisu_config.property.read_only()
                    mandatories(tiramisu_config, errors["errors"])
                    rougailconfig['display.output_format'] = "console"
                    export = RougailOutputDisplay(tiramisu_config,
                                                  rougailconfig=rougailconfig,
                                                  user_data_errors=errors['errors'],
                                                  user_data_warnings=errors['warnings'],
                                                  )
                    console = export.run()[1]
                    conv = Ansi2HTMLConverter(inline=True)
                    doc += inv_formatter.title('Output', 4)
                    cmd = CMD + f"-u yaml -yf {filename}"
                    with (dirname / "cmd_ro.txt").open("w") as fh:
                        fh.write(cmd)
                    doc += f"```shell\n{cmd}\n```\n"
                    conv_data = '<pre>' + conv.convert(console, full=False) + "</pre>\n"
                    with open(dirname / 'output_ro.html', 'w') as fh_output:
                        fh_output.write(conv_data)
                    rougailconfig['display.output_format'] = "github"
                    export = RougailOutputDisplay(tiramisu_config,
                                                  rougailconfig=rougailconfig,
                                                  user_data_errors=errors['errors'],
                                                  user_data_warnings=errors['warnings'],
                                                  )
                    doc += export.run()[1]
                    doc += "\n***\n"
                    if (dirname / 'invalid').is_file():
                        tiramisu_config.property.read_write()
                        errors2 = rougail.user_data(ret, invalid_user_data_error=True)
                        tiramisu_config.property.read_only()
                        mandatories(tiramisu_config, errors2["errors"])
                        rougailconfig['display.output_format'] = "console"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=rougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        console = export.run()[1]
                        conv = Ansi2HTMLConverter(inline=True)
                        doc += inv_formatter.title('Output when invalid user data is an error', 4)
                        cmd2 = cmd + " --cli.invalid_user_data_error"
                        with (dirname / "cmd_invalid.txt").open("w") as fh:
                            fh.write(cmd2)
                        doc += f"```shell\n{cmd2}\n```\n"
                        conv_data = '<pre>' + conv.convert(console, full=False) + "</pre>\n"
                        with open(dirname / 'output_invalid.html', 'w') as fh_output:
                            fh_output.write(conv_data)
                        rougailconfig['display.output_format'] = "github"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=rougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        doc += export.run()[1]
                        doc += "\n***\n"
                    if (dirname / 'unknown').is_file():
                        tiramisu_config.property.read_write()
                        trougailconfig = rougailconfig.copy()
                        errors2 = rougail.user_data(ret, unknown_user_data_error=True)
                        tiramisu_config.property.read_only()
                        mandatories(tiramisu_config, errors2["errors"])
                        trougailconfig['display.output_format'] = "console"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        console = export.run()[1]
                        conv = Ansi2HTMLConverter(inline=True)
                        doc += inv_formatter.title('Output when unknown user data is an error', 4)
                        cmd2 = cmd + " --cli.unknown_user_data_error"
                        with (dirname / "cmd_unknown.txt").open("w") as fh:
                            fh.write(cmd2)
                        doc += f"```shell\n{cmd2}\n```\n"
                        conv_data = '<pre>' + conv.convert(console, full=False) + "</pre>\n"
                        with open(dirname / 'output_unknown.html', 'w') as fh_output:
                            fh_output.write(conv_data)
                        trougailconfig['display.output_format'] = "github"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        doc += export.run()[1]
                        doc += "\n***\n"
                    if (dirname / 'root').is_file():
                        tiramisu_config.property.read_write()
                        trougailconfig = rougailconfig.copy()
                        errors2 = rougail.user_data(ret, unknown_user_data_error=True)
                        tiramisu_config.property.read_only()
                        with (dirname / 'root').open() as root_fh:
                            root_path = root_fh.read().strip()
                            root_tiramisu_config = tiramisu_config
                            for r in root_path.split('.'):
                                root_tiramisu_config = root_tiramisu_config.option(r)
                        mandatories(tiramisu_config, errors2["errors"])
                        trougailconfig['display.output_format'] = "console"
                        export = RougailOutputDisplay(root_tiramisu_config,
                                                      root_config=tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        console = export.run()[1]
                        conv = Ansi2HTMLConverter(inline=True)
                        doc += inv_formatter.title(f'Output for "{root_path}"', 4)
                        cmd2 = cmd + f" --cli.root {root_path}"
                        with (dirname / "cmd_root.txt").open("w") as fh:
                            fh.write(cmd2)
                        doc += f"```shell\n{cmd2}\n```\n"
                        conv_data = '<pre>' + conv.convert(console, full=False) + "</pre>\n"
                        with open(dirname / 'output_root.html', 'w') as fh_output:
                            fh_output.write(conv_data)
                        trougailconfig['display.output_format'] = "github"
                        export = RougailOutputDisplay(root_tiramisu_config,
                                                      root_config = tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        doc += export.run()[1]
                        doc += "\n***\n"
                    if (dirname / 'read_write').is_file():
                        trougailconfig = rougailconfig.copy()
                        tiramisu_config.property.read_write()
                        errors2 = rougail.user_data(ret, invalid_user_data_error=True)
                        trougailconfig['display.output_format'] = "console"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        console = export.run()[1]
                        conv = Ansi2HTMLConverter(inline=True)
                        doc += inv_formatter.title('Output in read write mode', 4)
                        cmd2 = cmd + " --cli.read_write"
                        with (dirname / "cmd_rw.txt").open("w") as fh:
                            fh.write(cmd2)
                        doc += f"```shell\n{cmd2}\n```\n"
                        conv_data = '<pre>' + conv.convert(console, full=False) + "</pre>\n"
                        with open(dirname / 'output_rw.html', 'w') as fh_output:
                            fh_output.write(conv_data)
                        trougailconfig['display.output_format'] = "github"
                        export = RougailOutputDisplay(tiramisu_config,
                                                      rougailconfig=trougailconfig,
                                                      user_data_errors=errors2['errors'],
                                                      user_data_warnings=errors2['warnings'],
                                                      )
                        doc += export.run()[1]
                        doc += "\n***\n"
                        tiramisu_config.property.read_only()
    #
    summary = Path('summary_after.md')
    if summary.is_file():
        with summary.open('r') as sfh:
            doc += '\n\n' + sfh.read()
    #
    doc_file = Path('README.md')
    with doc_file.open('w') as docfh:
        docfh.write(doc)
    with doc_file.open('w') as docfh:
        docfh.write(doc)
