#! /usr/bin/python3

import os
import re
import sys


class dkms_item:
    module : str = ""
    version : str = ""
    modulename : str = ""
    debpath : str = ""
    apt_dkms : str = ""
    arch = []
    rprovides = []
    needs_off_series : bool = False

    def __init__(self, module, version):
        self.module = module
        self.version = version
        self.modulename = ""
        self.debpath = ""
        self.apt_dkms = ""
        self.arch = []
        self.rprovides = []
        # DEFAULT = FALSE
        # If True, manually download the .deb from a specified pool
        # If False, uses the apt Build-Depends mechanism
        self.needs_off_series = False

    def getKernelTargetDirectory(self):
        return self.modulename + "-" + self.version

    def getDebFilename(self):
        if self.debpath == "":
            raise OSError("No debpath is defined")
        filename = re.sub(r'%package%', self.module, self.debpath)
        filename = re.sub(r'%version%', self.version, filename)
        filename = os.path.basename(filename)
        return filename

    def getProvidedDkms(self):
        provides = ""
        for p in self.rprovides:
            provides += p + " (= " + self.version + "), "
        return provides.strip().rstrip(',')

    def addModuleName(self, modulename):
        self.modulename = modulename

    def addArch(self, arch):
        self.arch.append(arch)

    def addRprovides(self, rprovides):
        self.rprovides.append(rprovides)

    def addDebPath(self, debpath):
        self.debpath = debpath
        if (self.apt_dkms == ""):
            m = re.match(r".*\/(.*)_%version%.*.deb", debpath, re.X)
            if m:
                self.apt_dkms = m.group(1)

    def addAptDkms(self, aptdkms):
        self.apt_dkms = aptdkms

    def setNeedsManualBuild(self, status: bool):
        self.needs_off_series = status

    def printModule(self):
        print("Module: " + self.module)
        print("Version: " + self.version)
        print("ModuleName: " + self.modulename)
        tmp = ""
        for item in self.arch:
            tmp += item + " "
        print("Arch: " + tmp)
        tmp = ""
        for item in self.rprovides:
            tmp += item + " "
        print("rprovides: " + tmp)
        print("debpath: " + self.debpath)
        print("apt_dkms: " + self.apt_dkms)
        print("needs_off_series: " + str(self.needs_off_series))

class dkms_modules:
    items : dkms_item = []

    def get_arch_has_modules(self, arch):
        for item in self.items:
            if arch in item.arch:
                return True
        return False

    def parse_module(self, dkms_line: str):
        params = dkms_line.split(" ")
        tmp = dkms_item(params[0].replace("\n",""),
                        params[1].replace("\n",""))
        for parm in params[2:]:
            if parm.startswith("modulename="):
                tmp.addModuleName(parm.split("=")[1].replace("\n",""))
            elif parm.startswith("arch="):
                tmp.addArch(parm.split("=")[1].replace("\n",""))
            elif parm.startswith("rprovides="):
                tmp.addRprovides(parm.split("=")[1].replace("\n",""))
            elif parm.startswith("debpath="):
                tmp.addDebPath(parm.split("=")[1].replace("\n",""))
            elif parm.startswith("off_series="):
                status = parm.split("=")[1].replace("\n","")
                if status.lower() == 'true':
                    tmp.setNeedsManualBuild(True)
                else:
                    tmp.setNeedsManualBuild(False)
        self.items.append(tmp)

    def print_modules(self):
        for item in self.items:
            item.printModule()
            print("")

    def return_prerequisites(self):
        res = ""
        length = len(self.items)
        for i, item in enumerate(self.items):
            res += " " + item.apt_dkms + " (= " + item.version + ") ["
            archs_len = len(item.arch)
            for j, arch in enumerate(item.arch):
                res += arch
                if (j < archs_len - 1):
                    res += " "
            res += "]"
            if i < length - 1:
                res += ",\n"

        return res


    def parse_dkms_version_file(self):
        self.items.clear()
        dkms_vf = open("debian/dkms-versions", "r")
        for item in dkms_vf:
            self.parse_module(item)

    # WARNING: DESTRUCTIVE PROCESS, deletes unrelated packages
    # Parse again if needs be
    def filter_per_architecture(self, architecture: str):
        self.items[:] = [x for x in self.items if architecture in x.arch]


    # WARNING: DESTRUCTIVE PROCESS, deletes unrelated packages
    # Parse again if needs be
    def filter_per_off_series(self):
        self.items[:] = [x for x in self.items if x.needs_off_series]

    # WARNING: DESTRUCTIVE PROCESS, deletes unrelated packages
    # Parse again if needs be
    def filter_per_build_depends_build(self):
        self.items[:] = [x for x in self.items if not x.needs_off_series]

# The following functions are used only for the manually built modules
def get_fake_dkms_root_folder():
    return os.path.join(
        os.getcwd(),
        "staging_dir",
        "linux-main-modules",
        "fake_dkms_root_folder",
        "")

def get_manual_dkms_build_folder():
    return os.path.join(
        os.getcwd(),
        "staging_dir",
        "linux-main-modules",
        "temp_dkms_build_folder",
        "")

def get_manual_dkms_output_folder():
    return os.path.join(
        os.getcwd(),
        "staging_dir",
        "linux-main-modules",
        "output_dkms",
        "")

# -----------------just for testing--------------------------------
#if __name__ == "__main__":
#    modules = dkms_modules()
#    modules.parse_dkms_version_file()
#    modules.filter_per_architecture("amd64")
#    modules.filter_per_off_series()
#    modules.print_modules()
