#!/usr/bin/env nix-shell
#!nix-shell -p nix-prefetch-git luarocks-nix python3 python3Packages.GitPython nix -i python3

# format:
# $ nix run nixpkgs.python3Packages.black -c black update.py
# type-check:
# $ nix run nixpkgs.python3Packages.mypy -c mypy update.py
# linted:
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265,E402 update.py

import inspect
import os
import tempfile
import shutil
from dataclasses import dataclass
import subprocess
import csv
import logging

from typing import List
from pathlib import Path

LOG_LEVELS = {
    logging.getLevelName(level): level for level in [
        logging.DEBUG, logging.INFO, logging.WARN, logging.ERROR ]
}

log = logging.getLogger()
log.addHandler(logging.StreamHandler())

ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent
from pluginupdate import Editor, parse_args, update_plugins, PluginDesc, CleanEnvironment

PKG_LIST="maintainers/scripts/luarocks-packages.csv"
TMP_FILE="$(mktemp)"
GENERATED_NIXFILE="pkgs/development/lua-modules/generated-packages.nix"
LUAROCKS_CONFIG="$NIXPKGS_PATH/maintainers/scripts/luarocks-config.lua"

HEADER = """
/* {GENERATED_NIXFILE} is an auto-generated file -- DO NOT EDIT!
Regenerate it with:
nixpkgs$ ./maintainers/scripts/update-luarocks-packages

You can customize the generated packages in pkgs/development/lua-modules/overrides.nix
*/
""".format(GENERATED_NIXFILE=GENERATED_NIXFILE)

FOOTER="""
}
/* GENERATED - do not edit this file */
"""

@dataclass
class LuaPlugin:
    name: str
    version: str
    server: str
    luaversion: str
    maintainers: str

    @property
    def normalized_name(self) -> str:
        return self.name.replace(".", "-")

# rename Editor to LangUpdate/ EcosystemUpdater
class LuaEditor(Editor):
    def get_current_plugins(self):
        return []

    def load_plugin_spec(self, input_file) -> List[PluginDesc]:
        luaPackages = []
        csvfilename=input_file
        log.info("Loading package descriptions from %s", csvfilename)


        with open(csvfilename, newline='') as csvfile:
            reader = csv.DictReader(csvfile,)
            for row in reader:
                # name,server,version,luaversion,maintainers
                plugin = LuaPlugin(**row)
                luaPackages.append(plugin)
        return luaPackages

    @property
    def attr_path(self):
        return "luaPackages"

    def get_update(self, input_file: str, outfile: str, _: int):

        def update() -> dict:
            plugin_specs = self.load_plugin_spec(input_file)

            self.generate_nix(plugin_specs, outfile)

            redirects = []
            return redirects

        return update

    def rewrite_input(self, *args, **kwargs):
        # not implemented yet
        pass

def generate_nix(
    plugins: List[LuaPlugin],
    outfilename: str
    ):
    sorted_plugins = sorted(plugins, key=lambda v: v.name.lower())

    # plug = {}
    # selon le manifest luarocks.org/manifest
    def _generate_pkg_nix(plug):
        cmd = [ "luarocks", "nix", plug.name]
        if plug.server:
            cmd.append(f"--only-server={plug.server}")

        if plug.maintainers:
            cmd.append(f"--maintainers={plug.maintainers}")

        if plug.version:
            cmd.append(plug.version)

        if plug.luaversion:
            with CleanEnvironment():
                local_pkgs = str(ROOT.resolve())
                cmd2 = ["nix-build", "--no-out-link", local_pkgs, "-A", f"{plug.luaversion}"]

                log.debug("running %s", cmd2)
                lua_drv_path=subprocess.check_output(cmd2, text=True).strip()
                cmd.append(f"--lua-dir={lua_drv_path}/bin")

        log.debug("running %s", cmd)
        output = subprocess.check_output(cmd, text=True)
        return output

    with tempfile.NamedTemporaryFile("w+") as f:
        f.write(HEADER)
        f.write("""
{ self, stdenv, lib, fetchurl, fetchgit, ... } @ args:
self: super:
with self;
{
""")

        for plugin in sorted_plugins:

            nix_expr = _generate_pkg_nix(plugin)
            f.write(f"{plugin.normalized_name} = {nix_expr}"
            )
        f.write(FOOTER)
        f.flush()

        # if everything went fine, move the generated file to its destination
        # using copy since move doesn't work across disks
        shutil.copy(f.name, outfilename)

    print(f"updated {outfilename}")

def load_plugin_spec():
    pass


def main():

    editor = LuaEditor("lua", ROOT, '', generate_nix,
        default_in = ROOT.joinpath(PKG_LIST),
        default_out = ROOT.joinpath(GENERATED_NIXFILE)
        )

    args = parse_args(editor)
    log.setLevel(LOG_LEVELS[args.debug])

    update_plugins(editor)


if __name__ == "__main__":

    main()

