import os
import subprocess
import xlsxwriter

def process():
    """
    Processes driver files for different oracles and collects statistics.

    This function performs the following steps:
    1. Creates a directory named "DRIVER-NUM-HAVOC" if it does not exist, or clears it if it does.
    2. Iterates over a list of oracles and processes each oracle.
    3. For each oracle, creates a corresponding text file to store results.
    4. Iterates over driver files in the specified drivers directory.
    5. For each driver file, runs a command using subprocess to perform havoc analysis.
    6. Parses the output of the command to extract the number of replacements and analysis times.
    7. Writes the collected statistics to the corresponding oracle text file.

    Note:
        The function assumes the existence of a directory "../downloaded_benchmarks/drivers/" containing driver files.
        The command "clam.py" should be available in the system's PATH.

    """
    path = "DRIVER-NUM-HAVOC"

    if os.path.exists(path):
        os.system(f"rm -rf {path}")
    os.mkdir(path)

    oracles = ["pos-nonrel", "def-nonrel", "pos-rel", "def-rel"]
    drivers_path = "../downloaded_benchmarks/drivers/"

    for oracle in oracles:
        oracle_file = os.path.join(path, oracle + ".txt")
        print(f"Processing {oracle} oracle")

        with open(oracle_file, "w") as f:
            f.write("\n")

        for driver in sorted(os.listdir(drivers_path)):
            driver_path = os.path.join(drivers_path, driver)
            print(f"Processing {driver_path}")

            if os.path.isfile(driver_path):
                cmd = ["clam.py", "--inline", f"--crab-havoc-analysis={oracle}", "--crab-dom=int", "--crab-print-invariants=false", driver_path]

                result = subprocess.run(cmd, capture_output=True, text=True)
                output_lines = result.stdout.split("\n")
                filtered_lines = [line for line in output_lines if ("Number of" in line or "Havoc " in line)]
                output_lines = filtered_lines
                print(output_lines)


                sum_checks = sum(
                    int(line.split()[4]) for line in output_lines if "Number of havocable checks" in line
                )

                sum_replacements = sum(
                    int(line.split()[3]) for line in output_lines if "Number of replacements" in line
                )

                sum_times = sum(
                    float(line.split()[4].replace('s', '')) for line in output_lines if "Havoc analysis time" in line
                )

                sum_times += sum(
                    float(line.split()[4].replace('s', '')) for line in output_lines if "Havoc propagation time" in line
                )

                with open(oracle_file, "a") as f:
                    f.write(f"{driver_path} {sum_checks} {sum_replacements} {sum_times}\n")


def dump_stats():
    """
    Reads data from text files for different oracles, processes the data, and writes it to an Excel file.

    The function performs the following steps:
    1. Defines the path and creates an Excel file using xlsxwriter.
    2. Iterates over a list of oracles and reads corresponding text files.
    3. Sorts and processes the lines from each text file using the drivers' names.
    4. Writes the processed data into separate worksheets in the Excel file.

    The text files are expected to contain lines with four space-separated values:
    - Driver: The name of the driver, which includes additional information separated by '--' and a file extension.
    - Checks: An integer value representing the number of checks.
    - Replacements: An integer value representing the number of replacements.
    - Time: A float value representing the time taken for the complete havoc processing.

    The Excel file will have the following columns:
    - Driver: The base name of the driver (extracted from the original driver name).
    - Checks: The number of checks.
    - Replacements: The number of replacements.
    - Time: The time taken.
    """
    path = "DRIVER-NUM-HAVOC"

    excel_file = os.path.join(path, f"DRIVER-NUM-HAVOC.xlsx")
    workbook = xlsxwriter.Workbook(excel_file)

    for oracle in ["pos-nonrel", "def-nonrel", "pos-rel", "def-rel"]:
        oracle_file = os.path.join(path, oracle + ".txt")

        with open(oracle_file, "r") as f:
            lines = f.readlines()

        lines.sort()
        lines = [line.strip() for line in lines]
        lines = [line for line in lines if line != ""]

        worksheet = workbook.add_worksheet(oracle)

        worksheet.write(0, 0, "Driver")
        worksheet.write(0, 1, "Checks")
        worksheet.write(0, 2, "Replacements")
        worksheet.write(0, 3, "Time")

        for i, line in enumerate(lines):
            driver, checks, replacements, time = line.split()
            # Keep only the driver name after the first -- but before the first .
            base_name = driver.split("--")[1:]
            # Join basename by inserting a -
            base_name = "-".join(base_name)
            # Remove the extension
            base_name = base_name.split(".")[0]
            worksheet.write(i + 1, 0, base_name)
            worksheet.write(i + 1, 1, int(checks))
            worksheet.write(i + 1, 2, int(replacements))
            worksheet.write(i + 1, 3, float(time))

    workbook.close()

if __name__ == "__main__":
    process()
    dump_stats()
