import os
import glob
import re
import subprocess

import setuptools
import setuptools.command.build_py
import debian.changelog


# Get version from debian/changelog
MINI_BUILDD_VERSION = str(debian.changelog.Changelog(file=open("./debian/changelog", "rb")).version)


class Scripts():
    _INSTALL_PATHS = {1: "usr/bin/", 8: "usr/sbin/"}

    def __init__(self):
        # Workaround: Auto-generate install files.
        self.debian_install = {1: open("debian/mini-buildd-utils.install", "w", encoding="UTF-8"),
                               8: open("debian/mini-buildd.install", "w", encoding="UTF-8")}
        # Workaround: dh_bash-completion format is very limited. The only way to automate this is to write the resp. configs here.
        self.debian_bash_completion = {1: open("debian/mini-buildd-utils.bash-completion", "w", encoding="UTF-8"),
                                       8: open("debian/mini-buildd.bash-completion", "w", encoding="UTF-8")}

        for i in 1, 8:
            self.debian_install[i].write("# Generated by setup.py\n")

        # Static install contents for mini-buildd
        self.debian_install[8].write(("share/package-templates/ /usr/share/mini-buildd/\n"
                                      "etc/schroot/\n"
                                      "etc/sudoers.d/\n"))

    def setup(self, prog_path, section):
        prog = os.path.basename(prog_path)
        man_page_file = f"{prog_path}.{section}"

        # Hack to get the DESCRIPTION from script for '--name' argument. See: https://lintian.debian.org/tags/manpage-has-useless-whatis-entry.html
        with open(f"{prog_path}") as prog_file:
            name = re.search(r'DESCRIPTION.*=.*"(.+?)"', prog_file.read()).group(1)

        print(f"I: Generating {man_page_file}...")
        subprocess.check_call(["help2man", "--no-info", "--name", name, "--version-string", MINI_BUILDD_VERSION, "--section", str(section), "--output", man_page_file, prog_path])

        # bash completion (python only)
        with open(f"{prog_path}") as prog_file:
            if re.match(r"#!/usr/bin/python", prog_file.readline()):
                bash_completion_file = f"src/{prog}.bash-completion"
                print(f"I: Generating {bash_completion_file}...")
                os.makedirs(os.path.dirname(bash_completion_file), exist_ok=True)
                with open(bash_completion_file, "w", encoding="UTF-8") as bash_completion:
                    bash_completion.write(f'eval "$(register-python-argcomplete3 --shell=bash "{prog}")"\n')
                self.debian_bash_completion[section].write(f"{bash_completion_file} {prog}\n")

        self.debian_install[section].write(f"{prog_path} {self._INSTALL_PATHS[section]}\n")


class BuildPy(setuptools.command.build_py.build_py):
    def run(self):
        init_file = "src/mini_buildd/__init__.py"
        print(f"I: Generating {init_file}...")
        with open(init_file, "w", encoding="UTF-8") as init_py:
            init_py.write(f"""\
# -*- coding: utf-8 -*-

__version__ = "{MINI_BUILDD_VERSION}\"
""")
        scripts = Scripts()
        scripts.setup("src/mini-buildd", 8)

        scripts.setup("src/mini-buildd-self-signed-certificate", 8)
        scripts.setup("src/mini-buildd-debootstrap-uname-2.6", 8)
        scripts.setup("src/mini-buildd-ssh-uploader-command", 8)
        scripts.setup("src/mini-buildd-ssh-client-command", 8)
        scripts.setup("src/mini-buildd-schroot-cleanup", 8)
        scripts.setup("src/mini-buildd-reject-cleanup", 8)
        scripts.setup("src/mini-buildd-import-08x", 8)

        scripts.setup("src/mini-buildd-api", 1)
        scripts.setup("src/mini-buildd-events", 1)
        scripts.setup("src/mini-buildd-dput", 1)
        scripts.setup("src/mini-buildd-super-portext", 1)

        super().run()


def package_data_files(directory, extensions):
    """Little helper to collect file lists for package_data."""
    package_path = "src/mini_buildd"
    result = []
    for extension in extensions:
        result += [f[len(package_path) + 1:] for f in glob.glob(f"{package_path}/{directory}/**/*.{extension}", recursive=True)]
    return result


setuptools.setup(
    cmdclass={"build_py": BuildPy},
    name="mini-buildd",
    version=MINI_BUILDD_VERSION.replace("+", ".").replace("~", "+"),  # Taint Debian version to make setuptools not warn
    package_dir={'': 'src'},
    description="Mini Debian build daemon",
    author="Stephan Sürken",
    author_email="absurd@debian.org",
    packages=["mini_buildd", "mini_buildd/models"],
    package_data={"mini_buildd":
                  package_data_files("templates", ["html", "txt"])
                  + package_data_files("templatetags", ["py"])
                  + package_data_files("static", ["svg", "css", "js", "ico"])})
