"""
Faraday Penetration Test IDE
Copyright (C) 2013  Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information
"""
import re
import os

from faraday_plugins.plugins.plugin import PluginBase

__author__ = "Francisco Amato"
__copyright__ = "Copyright (c) 2013, Infobyte LLC"
__credits__ = ["Francisco Amato"]
__license__ = ""
__version__ = "1.0.0"
__maintainer__ = "Francisco Amato"
__email__ = "famato@infobytesec.com"
__status__ = "Development"


class GoohostParser:
    """
    The objective of this class is to parse an xml file generated by the goohost tool.

    TODO: Handle errors.
    TODO: Test goohost output version. Handle what happens if the parser doesn't support it.
    TODO: Test cases.

    @param goohost_scantype You could select scan type ip, mail or host
    """

    def __init__(self, output, goohost_scantype, resolve_hostname):

        self.items = []
        self.resolve_hostname = resolve_hostname
        lines = list(filter(None, output.split('\n')))
        for line in lines:
            if goohost_scantype == 'ip':
                data = line.split()
                item = {'host': data[0], 'ip': data[1]}
                self.add_host_info_to_items(item['ip'], item['host'])
            elif goohost_scantype == 'host':
                data = line.strip()
                item = {'host': data, 'ip': self.resolve_hostname(data)}
                self.add_host_info_to_items(item['ip'], item['host'])
            else:
                item = {'data': line}

    def add_host_info_to_items(self, ip_address, hostname):
        data = {}
        exists = False
        for item in self.items:
            if ip_address in item['ip']:
                item['hosts'].append(hostname)
                exists = True

        if not exists:
            data['ip'] = ip_address
            data['hosts'] = [hostname]
            self.items.append(data)


class GoohostPlugin(PluginBase):
    """
    Example plugin to parse goohost output.
    """

    def __init__(self, *arg, **kwargs):
        super().__init__(*arg, **kwargs)
        self.id = "Goohost"
        self.name = "Goohost XML Output Plugin"
        self.plugin_version = "0.0.1"
        self.version = "v.0.0.1"
        self.options = None
        self._command_regex = re.compile(r'^(sudo goohost\.sh|goohost\.sh|sh goohost\.sh|\.\/goohost\.sh)\s+.*?')
        self.host = None
        self._command_string = None

    def parseOutputString(self, output):
        """
        This method will check if the import was made through the console or by importing a Goohost report.

        Import from Console:The method will take the path of the report generated by Goohost from the output the shell sends and will read
        the information from the txt where it expects it to be present.

        Import from Report: The method receives the output of the txt report as parameter.

        self.scantype defines the method used to generate the Goohost report

        """
        scantype = self.define_scantype_by_output(output)
        parser = GoohostParser(output, scantype, self.resolve_hostname)
        if scantype == 'host' or scantype == 'ip':
            for item in parser.items:
                h_id = self.createAndAddHost(item['ip'], hostnames=item['hosts'])
        del parser

    def define_scantype_by_command(self, command):
        method_regex = re.compile(r'-m (mail|host|ip)')
        method = method_regex.search(command)
        if method:
            return method.group(1)
        return 'host'

    def define_scantype_by_output(self, output):
        lines = output.split('\n')
        line = lines[0].split(' ')
        if len(line) == 1:
            return 'host'
        elif len(line) == 2:
            return 'ip'

    def get_report_path_from_output(self, command_output):
        report_name = re.search(r"Results saved in file (\S+)", command_output)
        if not report_name:
            return False
        else:
            self._output_file_path = os.path.join(self._current_path, report_name.group(1))
            if not os.path.exists(self._output_file_path):
                return False
            else:
                self._delete_temp_file = True

    def processOutput(self, command_output):
        self.get_report_path_from_output(command_output)
        if self.has_custom_output():
            self._parse_filename(self.get_custom_file_path())
        else:
            self.parseOutputString(command_output)


def createPlugin(*args, **kwargs):
    return GoohostPlugin(*args, **kwargs)
