import os

SUCCESS_PERCENTAGE_OK_TAG = 'Global percentage of requests OK is equal to'
MEAN_RESPONSE_TIME_OK_TAG = 'Global : mean response time is less than'
MEAN_RESPONSE_TIME_TAG = "> meanResponseTime"
REPORT_LOCATION_TAG = 'Please open the following file'
SUCCESS_PERCENTAGE_OK_KEY = 'success_percentage_ok'
MEAN_RESPONSE_TIME_OK_KEY = 'mean_response_time_ok'
REPORT_LOCATION_KEY = 'report_location'
MEAN_RESPONSE_TIME_KEY = 'mean_response_time'


class GatlingStdoutParser(object):

    def parse(self, out_io):
        ret = {
            SUCCESS_PERCENTAGE_OK_KEY: False,
            MEAN_RESPONSE_TIME_OK_KEY: False,
            MEAN_RESPONSE_TIME_KEY: None,
            REPORT_LOCATION_KEY: None
        }
        for line in out_io:
            if line.startswith(SUCCESS_PERCENTAGE_OK_TAG):
                if line[-5:-1] == 'true':
                    ret[SUCCESS_PERCENTAGE_OK_KEY] = True
            elif line.startswith(MEAN_RESPONSE_TIME_OK_TAG):
                if line[-5:-1] == 'true':
                    ret[MEAN_RESPONSE_TIME_OK_KEY] = True
            elif line.startswith(MEAN_RESPONSE_TIME_TAG):
                ret[MEAN_RESPONSE_TIME_KEY] = line.split()[2]
            elif line.startswith(REPORT_LOCATION_TAG):
                ret[REPORT_LOCATION_KEY] = line.split()[-1]
        return ret


class GatlingResult(dict):
    """
    Parses output generated by an iteration of gatling testing
    """

    def __init__(self, users, duration, webheads):
        """
        Initializes to default dict and then parses output

        :param output: StringIO buffer to read from
        """
        self.update({
            'users': users,
            'duration': duration,
            'webheads': webheads,
            SUCCESS_PERCENTAGE_OK_KEY: False,
            MEAN_RESPONSE_TIME_OK_KEY: False,
            MEAN_RESPONSE_TIME_KEY: None,
            REPORT_LOCATION_KEY: None
        })

    def _parse(self, output):
        """
        Parses the StringIO buffer output.  Results are stored
        over what is already saved.

        :param output: StringIO Buffer to parse from
        """
        for line in output:
            if line.startswith(SUCCESS_PERCENTAGE_OK_TAG):
                if line[-5:-1] == 'true':
                    self[SUCCESS_PERCENTAGE_OK_KEY] = True
            elif line.startswith(MEAN_RESPONSE_TIME_OK_TAG):
                if line[-5:-1] == 'true':
                    self[MEAN_RESPONSE_TIME_OK_KEY] = True
            elif line.startswith(MEAN_RESPONSE_TIME_TAG):
                self[MEAN_RESPONSE_TIME_KEY] = line.split()[2]
            elif line.startswith(REPORT_LOCATION_TAG):
                self[REPORT_LOCATION_KEY] = line.split()[-1]

    @property
    def success(self):
        """
        Returns boolean indicating a successful iteration

        :returns: Boolean
        """
        return self[SUCCESS_PERCENTAGE_OK_KEY] and \
            self[MEAN_RESPONSE_TIME_OK_KEY]

    @property
    def report(self):
        """
        Returns the gatling created html report location of the iteration.

        :return: String
        """
        return self.get(REPORT_LOCATION_KEY, None)

    @property
    def simulation_log(self):
        """
        Returns the gatling created simulation.log location of the iteration.

        :return: String
        """
        report = self.report
        if report is not None:
            return os.path.join(os.path.dirname(report), 'simulation.log')
        return report

    @property
    def webheads(self):
        """
        Returns the list of webheads for this iteration.

        :return: List
        """
        return self.get('webheads', None)

    @property
    def users(self):
        """
        Returns the number of total users for this iteration.
        The users supplied to gatling are per webhead.

        :return: Integer
        """
        users = self.get('users', None)
        if users is not None:
            users = users * len(self.webheads)
        return users

    @property
    def duration(self):
        """
        Returns the duration of this iteration in seconds.

        :return: Integer
        """
        return self.get('duration', None)

    @property
    def mean_response_time(self):
        """
        Returns the mean response time in milliseconds for this iteration.

        :return: Integer
        """
        return self.get(MEAN_RESPONSE_TIME_KEY, None)

    def __str__(self):
        """
        Returns the string representation of this iteration.

        :return: String
        """
        return "\n\t".join([
            "Gatling Iteration of %s users over %s seconds" %
            (self.users, self.duration),
            "Webheads: %s" % self.webheads,
            "Successful: %s" % self.success,
            "Successful request percentage pass: %s" %
            self[SUCCESS_PERCENTAGE_OK_KEY],
            "Mean response time pass: %s" % self[MEAN_RESPONSE_TIME_OK_KEY],
            "Mean response time: %s ms" % self.mean_response_time,
            "Report location: %s" % self.report,
            "Simulation log: %s" % self.simulation_log])
