"""
This file contains the command to compile the driver

"""
import glob
import os
import re
import shutil
import subprocess
import sys
import tempfile
import click

import sys
if sys.version_info[:2] >= (3, 8):
    # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
    from importlib.metadata import entry_points  # pragma: no cover
else:
    from importlib_metadata import entry_points  # pragma: no cover


def index_containing_substring(the_list, substring, start=0):
    for i in range(start, len(the_list)):
        if substring in the_list[i]:
            return i
    return -1


def find_modinc():
    #Looks for halcompile and if found returns the path to Makefile.modinc
    click.echo(click.style("INFO", fg="bright_blue") + ": Looking for halcompile...")
    halcompile = shutil.which('halcompile')
    if not halcompile:
            raise SystemExit("Unable to locate halcompile, is it installed?")
    try:
        click.echo(click.style("INFO", fg="bright_blue") + ": Locating Makefile.modinc...")
        modinc_loc = subprocess.run(["halcompile --print-modinc"], check = True, shell=True, capture_output=True, text=True)
    except subprocess.CalledProcessError:
        raise SystemExit("halcompile --print-modinc failed")
    return (modinc_loc.stdout).rstrip()



def find_rtlib_dir(modinc_path):
    # Parses Makefile.modinc checks for RIP install or not and returns the install directory for the modules
    f = open(f'{modinc_path}','r')
    lines = f.read().splitlines() # List with stripped line-breaks
    f.close()                     # Close file

    index = index_containing_substring (lines, 'RUN_IN_PLACE=')
    rip_tmp = re.sub(' ', '',lines[index]).partition('=')

    index = index_containing_substring (lines, 'RTLIBDIR :=')
    rip_tmp = re.sub(' ', '',lines[index]).partition('=')
    rip_yes = rip_tmp[2]

    index = index_containing_substring (lines, 'RTLIBDIR :=',index+2)
    rip_tmp=re.sub(' ', '',lines[index]).partition('=')
    rip_no = rip_tmp[2]

    if rip_tmp[2] == 'yes':
        click.echo(click.style("INFO: Run In Place (RIP) Installation detected", fg="bright_red", blink=True))
        return rip_yes
    else:
        click.echo(click.style("INFO: Run In Place (RIP) Installation not detected", fg="bright_green", blink=True))
        return rip_no

@click.command()
@click.option('--modules', '-m', multiple=True)
@click.option('--rtlib', '-m', type=str, help="Override the path where all modules are installed (normally auto-detected).")

def cli(modules, rtlib):
    """Installs the LitexCNC driver using halcompile."""

    with tempfile.TemporaryDirectory() as temp_dir:
        driver_files_group = "litexcnc.driver_files"
        entries = entry_points()
        driver_files = {}
        if hasattr(entries, "select"):
            # The select method was introduced in importlib_metadata 3.9 (and Python 3.10)
            # and the previous dict interface was declared deprecated
            driver_folders = entries.select(group=driver_files_group)  # type: ignore
        else:
            # TODO: Once Python 3.10 becomes the oldest version supported, this fallback and
            #       conditional statement can be removed.
            driver_folders = (extension for extension in entries.get(driver_files_group, []))  # type: ignore
        for driver_folder in driver_folders:
            # Add the files to the list
            driver_files[driver_folder.name] = driver_folder.load().FILES

        # List with files for the compile-script
        files_to_compiles = []

        # Create the file config.h
        if not rtlib:
             modinc = find_modinc()
             rtlib = find_rtlib_dir(modinc)
             click.echo(click.style("INFO", fg="bright_blue") + f": Detected EMC2_RTLIB_DIR location '{rtlib}'")
        else:
             click.echo(click.style("INFO", fg="bright_yellow") + f": User specified EMC2_RTLIB_DIR location '{rtlib}'")             
   

        f = open(os.path.join(temp_dir, 'config.h'),'w')

        print("/**", file=f)
        print(" * THIS FILE IS AUTOGENERATED BY HALCOMPILE.PY, CHANGES WILL BE OVERWRITTEN", file=f)
        print(" */", file=f)
        print("#ifndef __INCLUDE_LITEXCNC_CONFIG_H__", file=f)
        print("#define __INCLUDE_LITEXCNC_CONFIG_H__", file=f)
        print("", file=f)
        print(f"#define EMC2_RTLIB_DIR \"{rtlib}\"", file=f)
        print("", file=f)
        print("#endif /* __INCLUDE_LITEXCNC_CONFIG_H__ */", file=f)
        f.close()

        
        
        # Copy the files to the temp directory
        click.echo(click.style("INFO", fg="bright_blue") + ": Retrieving default driver files to compile...")
        if  not modules or 'default' in modules:
            files_to_compiles.append('litexcnc.c')
        for file in driver_files.pop('default'):
            click.echo(f"Copying file '{file.name}'")
            shutil.copy2(
                os.path.join(file),
                os.path.join(temp_dir, os.path.basename(file.name))
            )
            if not modules or 'default' in modules:
                if re.search("litexcnc_.*\.c", file.name):
                    files_to_compiles.append(file.name)
        if driver_files.keys():
            click.echo(click.style("INFO", fg="bright_blue") + ": Retrieving extra modules / boards to compile...")
            for extra in driver_files.keys():
                for file in driver_files[extra]:
                    click.echo(f"Copying file '{file.name}'")
                    shutil.copy2(
                        os.path.join(file),
                        os.path.join(temp_dir, os.path.basename(file.name))
                    )
                    if not modules or extra in modules:
                        if re.search("litexcnc_.*\.c", file.name):
                            files_to_compiles.append(file.name)

        # Compile the driver
        click.echo(click.style("INFO", fg="bright_blue") + ": Compiling LitexCNC driver...")
        ret = subprocess.call(
            f'halcompile --install {" ".join(files_to_compiles)}',
            cwd=temp_dir,
            shell=True
        )
        if ret:
            click.echo(click.style("Error", fg="red") + ": Compilation of the driver failed.")
            return
    # Done!
    click.echo(click.style("INFO", fg="bright_blue") + ": LitexCNC driver installed")

