#!/usr/bin/env python3
#
# Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
"""Tool used for rendering Dart Native Runtime wiki as HTML.

Usage: runtime/tools/wiki/build/build.py [--deploy]

If invoked without --deploy the tool would serve development version of the
wiki which supports fast edit-(auto)refresh cycle.

If invoked with --deploy it would build deployment version in the
/tmp/dart-vm-wiki directory.
"""

from __future__ import annotations

import logging
import os
import re
import shutil
import subprocess
from pathlib import Path
from typing import Callable, Dict, Sequence

import argparse
import asyncio
import codecs
import coloredlogs
import jinja2
import markdown

from aiohttp import web, WSCloseCode, WSMsgType
from markdown.extensions.codehilite import CodeHiliteExtension
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
from xrefs import XrefExtension
from admonitions import convert_admonitions

# Configure logging to use colors.
coloredlogs.install(level='INFO',
                    fmt='%(asctime)s - %(message)s',
                    datefmt='%H:%M:%S')

# Declare various directory paths.
# We expected to be located in runtime/tools/wiki/build.
TOOL_DIR = os.path.dirname(os.path.realpath(__file__))
SDK_DIR = os.path.relpath(os.path.join(TOOL_DIR, '..', '..', '..', '..'))

WIKI_SOURCE_DIR = os.path.join(SDK_DIR, 'runtime', 'docs')

STYLES_DIR = os.path.relpath(os.path.join(TOOL_DIR, '..', 'styles'))
STYLES_INCLUDES_DIR = os.path.join(STYLES_DIR, 'includes')

TEMPLATES_DIR = os.path.relpath(os.path.join(TOOL_DIR, '..', 'templates'))
TEMPLATES_INCLUDES_DIR = os.path.join(TEMPLATES_DIR, 'includes')

PAGE_TEMPLATE = 'page.html'

OUTPUT_DIR = '/tmp/dart-vm-wiki'
OUTPUT_CSS_DIR = os.path.join(OUTPUT_DIR, 'css')

# Clean output directory and recreate it.
shutil.rmtree(OUTPUT_DIR, ignore_errors=True)
os.makedirs(OUTPUT_DIR, exist_ok=True)
os.makedirs(OUTPUT_CSS_DIR, exist_ok=True)

# Parse incoming arguments.
parser = argparse.ArgumentParser()
parser.add_argument('--deploy', dest='deploy', action='store_true')
parser.add_argument('--deployment-root', dest='deployment_root', default='')
parser.set_defaults(deploy=False)
args = parser.parse_args()

is_dev_mode = not args.deploy
deployment_root = args.deployment_root

# Initialize jinja environment.
jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATES_DIR),
                                lstrip_blocks=True,
                                trim_blocks=True)


class Artifact:
    """Represents a build artifact with its dependencies and way of building."""

    # Map of all discovered artifacts.
    all: Dict[str, Artifact] = {}

    # List of listeners which are notified whenever some artifact is rebuilt.
    listeners: list[Callable] = []

    def __init__(self, output: str, inputs: Sequence[str]):
        Artifact.all[output] = self
        self.output = output
        self.inputs = [os.path.normpath(input) for input in inputs]

    def depends_on(self, path: str) -> bool:
        """Check if this"""
        return path in self.inputs

    def build(self):
        """Convert artifact inputs into an output."""

    @staticmethod
    def build_all():
        """Build all artifacts."""
        Artifact.build_matching(lambda obj: True)

    @staticmethod
    def build_matching(predicate: Callable[[Artifact], bool]):
        """Build all artifacts matching the given filter."""
        rebuilt = False
        for _, artifact in Artifact.all.items():
            if predicate(artifact):
                artifact.build()
                rebuilt = True

        # If any artifacts were rebuilt notify the listeners.
        if rebuilt:
            for listener in Artifact.listeners:
                listener()


xref_extension = XrefExtension()


class Page(Artifact):
    """A single wiki Page (a markdown file)."""

    def __init__(self, name: str):
        self.name = name
        output_name = 'index' if name == 'README' else name
        super().__init__(os.path.join(OUTPUT_DIR, f'{output_name}.html'),
                         [os.path.join(WIKI_SOURCE_DIR, f'{name}.md')])

    def __repr__(self):
        return f'Page({self.output} <- {self.inputs[0]})'

    def depends_on(self, path: str):
        return path.startswith(TEMPLATES_INCLUDES_DIR) or super().depends_on(
            path)

    def _load_markdown(self):
        with open(self.inputs[0], 'r', encoding='utf-8') as file:
            content = file.read()

            # Remove autogenerated xref section.
            content = re.sub(r'<!\-\- AUTOGENERATED XREF SECTION \-\->.*$',
                             '',
                             content,
                             flags=re.DOTALL)

            return convert_admonitions(content)

    def _update_xref_section(self, xrefs):
        with open(self.inputs[0], 'r', encoding='utf-8') as file:
            content = file.read()
        section = '\n'.join(
            ['', '<!-- AUTOGENERATED XREF SECTION -->'] +
            [f'[{key}]: {value}' for key, value in xrefs.items()])
        with open(self.inputs[0], 'w', encoding='utf-8') as file:
            content = re.sub(r'\n<!-- AUTOGENERATED XREF SECTION -->.*$',
                             '',
                             content,
                             flags=re.DOTALL)
            content += section
            file.write(content)

    def build(self):
        logging.info('Build %s from %s', self.output, self.inputs[0])

        template = jinja2_env.get_template(PAGE_TEMPLATE)
        md_converter = markdown.Markdown(extensions=[
            'admonition',
            'extra',
            CodeHiliteExtension(),
            'tables',
            'pymdownx.superfences',
            'toc',
            xref_extension,
        ])
        result = template.render({
            'dev':
            is_dev_mode,
            'body':
            md_converter.convert(self._load_markdown()),
            'root':
            deployment_root
        })
        # pylint: disable=no-member
        if not is_dev_mode and len(md_converter.xrefs) > 0:
            self._update_xref_section(md_converter.xrefs)

        os.makedirs(os.path.dirname(self.output), exist_ok=True)
        with codecs.open(self.output, "w", encoding='utf-8') as file:
            file.write(result)

        template_filename = template.filename  # pytype: disable=attribute-error
        self.inputs = [self.inputs[0], template_filename]


class Style(Artifact):
    """Stylesheet written in SASS which needs to be compiled to CSS."""

    def __init__(self, name: str):
        self.name = name
        super().__init__(os.path.join(OUTPUT_CSS_DIR, name + '.css'),
                         [os.path.join(STYLES_DIR, name + '.scss')])

    def __repr__(self):
        return f'Style({self.output} <- {self.inputs[0]})'

    def depends_on(self, path: str):
        return path.startswith(STYLES_INCLUDES_DIR) or super().depends_on(path)

    def build(self):
        logging.info('Build %s from %s', self.output, self.inputs[0])
        subprocess.call(['sass', self.inputs[0], self.output])


def find_images_directories():
    """Find all subdirectories called images within wiki."""
    return [
        f.relative_to(Path(WIKI_SOURCE_DIR)).as_posix()
        for f in Path(WIKI_SOURCE_DIR).rglob('images')
    ]


def find_artifacts():
    """Find all wiki pages and styles and create corresponding Artifacts."""
    Artifact.all = {}
    for file in Path(WIKI_SOURCE_DIR).rglob('*.md'):
        name = file.relative_to(Path(WIKI_SOURCE_DIR)).as_posix().rsplit(
            '.', 1)[0]
        Page(name)

    for file in Path(STYLES_DIR).glob('*.scss'):
        Style(file.stem)


def build_for_deploy():
    """Create a directory which can be deployed to static hosting."""
    logging.info('Building wiki for deployment into %s', OUTPUT_DIR)
    Artifact.build_all()
    for images_dir in find_images_directories():
        src = os.path.join(WIKI_SOURCE_DIR, images_dir)
        dst = os.path.join(OUTPUT_DIR, images_dir)
        logging.info('Copying %s <- %s', dst, src)
        shutil.rmtree(dst, ignore_errors=True)
        shutil.copytree(src, dst)

    # Some images directories contain OmniGraffle source files which need
    # to be removed before
    logging.info('Removing image source files (*.graffle)')
    for graffle in Path(OUTPUT_DIR).rglob('*.graffle'):
        logging.info('... removing %s', graffle.as_posix())


class ArtifactEventHandler(FileSystemEventHandler):
    """File system listener rebuilding artifacts based on changed paths."""

    def on_modified(self, event):
        path = os.path.relpath(event.src_path, '.')
        Artifact.build_matching(lambda artifact: artifact.depends_on(path))


def serve_for_development():
    """Serve wiki for development (with hot refresh)."""
    logging.info('Serving wiki for development')
    Artifact.build_all()

    # Watch for file modifications and rebuild dependant artifacts when their
    # dependencies change.
    event_handler = ArtifactEventHandler()
    observer = Observer()
    observer.schedule(event_handler, TEMPLATES_DIR, recursive=False)
    observer.schedule(event_handler, WIKI_SOURCE_DIR, recursive=True)
    observer.schedule(event_handler, STYLES_DIR, recursive=True)
    observer.start()

    async def on_shutdown(app):
        for ws in app['websockets']:
            await ws.close(code=WSCloseCode.GOING_AWAY,
                           message='Server shutdown')
        observer.stop()
        observer.join()

    async def handle_artifact(name):
        source_path = os.path.join(OUTPUT_DIR, name)
        logging.info('Handling source path %s for %s', source_path, name)
        if source_path in Artifact.all:
            return web.FileResponse(source_path)
        else:
            return web.HTTPNotFound()

    async def handle_page(request):
        name = request.match_info.get('name', 'index.html')
        if name == '' or name.endswith('/'):
            name = name + 'index.html'
        return await handle_artifact(name)

    async def handle_css(request):
        name = request.match_info.get('name')
        return await handle_artifact('css/' + name)

    async def websocket_handler(request):
        logging.info('websocket connection open')
        ws = web.WebSocketResponse()
        await ws.prepare(request)

        loop = asyncio.get_event_loop()

        def notify():
            logging.info('requesting reload')
            asyncio.run_coroutine_threadsafe(ws.send_str('reload'), loop)

        Artifact.listeners.append(notify)
        request.app['websockets'].append(ws)
        try:
            async for msg in ws:
                if msg.type == WSMsgType.ERROR:
                    logging.error(
                        'websocket connection closed with exception %s',
                        ws.exception())
        finally:
            logging.info('websocket connection closing')
            Artifact.listeners.remove(notify)
            request.app['websockets'].remove(ws)

        logging.info('websocket connection closed')
        return ws

    app = web.Application()
    app['websockets'] = []
    for images_dir in find_images_directories():
        app.router.add_static('/' + images_dir,
                              os.path.join(WIKI_SOURCE_DIR, images_dir))
    app.router.add_get('/ws', websocket_handler)
    app.router.add_get('/css/{name}', handle_css)
    app.router.add_get('/{name:[^{}]*}', handle_page)
    app.on_shutdown.append(on_shutdown)
    web.run_app(app, access_log_format='"%r" %s')


def main():
    """Main entry point."""
    find_artifacts()
    if is_dev_mode:
        serve_for_development()
    else:
        build_for_deploy()


if __name__ == '__main__':
    main()
