import json
import logging
from pathlib import Path
from subprocess import PIPE

import click
from parsing import DetectMaliciousLogs, ParsingDumps
from static_analysis import (
    BasicStaticAnalysis,
    DetectAntiTechniques,
    PackerDetection,
    PEFileInfo,
    Report,
    SignatureBasedDetection,
)

DEPS_DIR = Path(__file__) / "../deps"
DEPS_DIR = DEPS_DIR.absolute().resolve()


@click.group()
def main():
    logging.basicConfig(
        level=logging.DEBUG,
        format="[%(asctime)s][%(levelname)s] %(message)s",
        handlers=[logging.StreamHandler()],
    )


@click.command(short_help="parse dumps generated during monitoring")
@click.argument("path", type=click.Path(exists=True))
@click.argument("outputs")
def parse_dumps(path, outputs):
    """
    This command will parse the outputs generated by monitoring.exe

    PATH should contain the path to the logs

    OUTPUTS should  have the folder to put the parsed outputs
    """
    output_dir = Path(outputs)
    output_dir.mkdir(parents=True, exist_ok=True)

    parse_data = ParsingDumps()
    parse_data.run(log_dir=path, output_dir=output_dir)

    detect_malicious_logs = DetectMaliciousLogs(
        dumps_dir=output_dir / "parsed_dumps", ioc_dir=DEPS_DIR / "IOC"
    )
    detect_malicious_logs.run("log_report.json", "required_file.txt")


@click.command(short_help="perform static analysis on files")
@click.argument("path", type=click.Path(exists=True))
@click.argument("outputs", type=click.Path(exists=True))
def static_analysis(path, outputs):
    """
    This command will perform static analysis for the files present inside PATH

    OUTPUTS should be the same folder as given in parse-dumps
    """

    files_dir = Path(path)
    files = files_dir.rglob("*")

    output_dir = Path(outputs)
    base_dir = output_dir / "static_analysis"
    process_dir = output_dir / "parsed_dumps" / "process"

    for file in files:
        file_name = file.name.split(".")[0]

        file_directory = base_dir / file_name
        file_directory.mkdir(parents=True, exist_ok=True)

        ApiCalls = set()
        with open(process_dir / f"{file_name}.json", "r") as api_log:
            data = json.loads(api_log.read())

            ApiHooks = data["Events"]
            for apicall in ApiHooks:
                ApiCalls.add(apicall[0])

        # needed in DetectAntiTechniques and PackerDetection
        report = Report()

        # DETECT ANTI TECHNIQUES
        detect_anti_techniques = DetectAntiTechniques(files_dir / file.name, report)
        detect_anti_techniques.run(ApiCalls, ApiHooks)

        # BASIC STATIC ANALYSIS
        basic_static_analysis = BasicStaticAnalysis(files_dir / file.name)
        basic_static_analysis.run(file_directory / "basic_static_analysis.json")

        # PACKER DETECTION
        packer_detection = PackerDetection(
            files_dir / file.name, report, deps_dir=DEPS_DIR
        )
        packer_detection.run()

        # MAKING A JSON REPORT
        report_dict = {
            "[DETECTIONS]": report.GetDetections(),
            "[SUSPICIONS]": report.GetSuspicions(),
        }
        json_report = json.dumps(report_dict, indent=4)

        # LOGGING TO THE FILE
        with open(file_directory / "report.json", "w") as report_file:
            report_file.write(json_report)

        # PEFILE INFO
        pe_file_info = PEFileInfo(files_dir / file.name)
        pe_file_info.run(file_directory / "pe_file_info.json")

        # Signature Based Detection using clamAV and Yara
        signature = SignatureBasedDetection(
            str(files_dir / file.name), deps_dir=DEPS_DIR
        )

        # SIGNATURE BASED DETECTION
        signature.run(
            file_directory / "yara_signature_based_analysis.json",
            file_directory / "clamav_signature_based_analysis.txt",
        )

    logging.info(f"Analysis is done, you can find the files at {output_dir.absolute()}")


main.add_command(parse_dumps)
main.add_command(static_analysis)

if __name__ == "__main__":
    main()
