import argparse
import sys
from pathlib import Path
from subprocess import call

import yaml  # type: ignore
from dirsync import sync

from lndocs._generate_conf import generate_conf

from ._postprocess import (
    replace_image_targets,
    replace_index_targets,
    update_index_file,
)

HERE = Path(__file__).parent


def get_lamin_project():
    with open("./lamin-project.yaml") as f:
        try:
            return yaml.safe_load(f)
        except yaml.YAMLError as exc:
            print(exc)
            quit()


def main():
    parser = argparse.ArgumentParser(description="Build Lamin website.")
    aa = parser.add_argument
    aa("--show", action="store_true", help="launch server & show")
    aa("--docs", type=str, default="docs", help="directory with docs sources")
    aa("--site", type=str, default="_build/html", help="output directory")
    aa("--live", action="store_true", help="use autobuild")
    args = parser.parse_args()
    if not Path(args.docs).exists():
        sys.exit(
            f"The source directory {args.docs} does not exist! Change to repo root!"
        )
    if not Path("./lamin-project.yaml").exists():
        sys.exit("The ./lamin-project.yaml conf file does not exist!")
    lamin_project = get_lamin_project()

    sync(str(HERE / "lamin_sphinx"), "./lamin_sphinx", "sync", create=True, ctime=True)
    # check whether we need to generate the conf.py for Sphinx
    # input for it is the lamin-project.yaml file
    generate_conf_check = False
    conf_file = Path(args.docs) / "conf.py"
    if not conf_file.exists():
        generate_conf_check = True
    else:
        with open(conf_file) as f:
            first_line = f.readline()
        if first_line == "# auto-generated by lndocs\n":
            generate_conf_check = True
    if generate_conf_check:
        generate_conf(args.docs)

    if args.live:
        build_command = "sphinx-autobuild"
    else:
        build_command = "sphinx-build"

    # all of what follows here is about getting rid of the back-slash for index files
    # on URLs for the dedicated docs pages
    docs_dir = args.docs
    check_postprocess = not args.live and generate_conf_check
    notebooks = []
    if check_postprocess:
        docs_dir = Path(f"_{args.docs}_tmp/")
        sync(
            args.docs,
            Path(docs_dir) / lamin_project["project_slug"],
            "sync",
            create=True,
        )
        (docs_dir / lamin_project["project_slug"] / "conf.py").rename(
            docs_dir / "conf.py"
        )
        for path in docs_dir.glob("**/*"):
            if path.suffix not in {".md", ".ipynb"}:
                continue
            if ".ipynb_checkpoints/" in str(path):
                continue
            if path.suffix == ".ipynb":
                # test whether prefix is capital letter or digit and if so,
                # strip them for pretty & persistent urls we need the prefixes
                # on notebooks to allow users to navigate downloaded notebooks
                # that should display in order in a file browser
                prefix = path.stem[0]
                if prefix.isdigit() or prefix.isupper() and "-" in path.stem:
                    new_stem = "-".join(path.stem.split("-")[1:])
                    # path.with_stem() is >3.9
                    new_path = path.with_name(f"{new_stem}{path.suffix}")
                    path.rename(new_path)
                    path = new_path
                notebooks.append(path)
            if path.is_file():
                replace_index_targets(path, lamin_project["project_slug"])
            if str(path).endswith("index.md"):
                update_index_file(path)
        (docs_dir / f"{lamin_project['project_slug']}.md").rename(docs_dir / "index.md")
    # end of _docs_tmp

    build_status = call(f"{build_command} {docs_dir} {args.site}", shell=True)

    # delete auto-generated files
    if "package_name" in lamin_project:
        package_name = lamin_project["package_name"]
        for generated in Path(args.docs).glob(f"{package_name}.*.rst"):
            generated.unlink()

    site = Path(args.site)

    # move Jupyter-generated images to accessible location
    # as the root isn't part of the deployed website!
    if check_postprocess and (site / "_images").exists():
        for path in notebooks:
            path_html = (
                str(path).replace(str(docs_dir), str(site)).replace(".ipynb", ".html")
            )
            replace_image_targets(path_html, lamin_project["project_slug"])
        sync(
            site / "_images/",
            site / lamin_project["project_slug"] / "_images/",
            "sync",
            create=True,
        )

    if not args.show:
        if lamin_project["project_slug"] == "":  # deploy a copy of _static on Netlify
            sync(site / "_static", site / "docs/_static", "sync", create=True)
        return build_status
    else:
        if build_status == 0:
            call("cd _build/html; python -m http.server", shell=True)
