# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import io
import json
import logging
import os
import subprocess

from mobly import utils

MOBLY_CONTROLLER_CONFIG_NAME = "IPerfServer"


def create(configs):
  results = []
  for c in configs:
    try:
      results.append(IPerfServer(c, logging.log_path))
    except:
      pass
  return results


def destroy(objs):
  for ipf in objs:
    try:
      ipf.stop()
    except:
      pass


class IPerfResult(object):

  def __init__(self, result_path):
    try:
      with io.open(result_path, 'r', encoding='utf-8') as f:
        self.result = json.load(f)
    except ValueError:
      with io.open(result_path, 'r', encoding='utf-8') as f:
        # Possibly a result from interrupted iperf run, skip first line
        # and try again.
        lines = f.readlines()[1:]
        self.result = json.loads(''.join(lines))

  def _has_data(self):
    """Checks if the iperf result has valid throughput data.

        Returns:
            True if the result contains throughput data. False otherwise.
        """
    return ('end' in self.result) and ('sum' in self.result["end"])

  def get_json(self):
    """
        Returns:
            The raw json output from iPerf.
        """
    return self.result

  @property
  def error(self):
    if 'error' not in self.result:
      return None
    return self.result['error']

  @property
  def avg_rate(self):
    """Average receiving rate in MB/s over the entire run.

        If the result is not from a success run, this property is None.
        """
    if not self._has_data or 'sum' not in self.result['end']:
      return None
    bps = self.result['end']['sum']['bits_per_second']
    return bps / 8 / 1024 / 1024

  @property
  def avg_receive_rate(self):
    """Average receiving rate in MB/s over the entire run. This data may
        not exist if iperf was interrupted.

        If the result is not from a success run, this property is None.
        """
    if not self._has_data or 'sum_received' not in self.result['end']:
      return None
    bps = self.result['end']['sum_received']['bits_per_second']
    return bps / 8 / 1024 / 1024

  @property
  def avg_send_rate(self):
    """Average sending rate in MB/s over the entire run. This data may
        not exist if iperf was interrupted.

        If the result is not from a success run, this property is None.
        """
    if not self._has_data or 'sum_sent' not in self.result['end']:
      return None
    bps = self.result['end']['sum_sent']['bits_per_second']
    return bps / 8 / 1024 / 1024


class IPerfServer():
  """Class that handles iperf3 operations.
    """

  def __init__(self, port, log_path):
    self.port = port
    self.log_path = os.path.join(log_path, "iPerf{}".format(self.port))
    self.iperf_str = "iperf3 -s -J -p {}".format(port)
    self.iperf_process = None
    self.log_files = []
    self.started = False

  def start(self, extra_args="", tag=""):
    """Starts iperf server on specified port.

        Args:
            extra_args: A string representing extra arguments to start iperf
                server with.
            tag: Appended to log file name to identify logs from different
                iperf runs.
        """
    if self.started:
      return
    utils.create_dir(self.log_path)
    if tag:
      tag = tag + ','
    out_file_name = "IPerfServer,{},{}{}.log".format(self.port, tag,
                                                     len(self.log_files))
    full_out_path = os.path.join(self.log_path, out_file_name)
    cmd = '%s %s > %s' % (self.iperf_str, extra_args, full_out_path)
    self.iperf_process = utils.start_standing_subprocess(cmd, shell=True)
    self.log_files.append(full_out_path)
    self.started = True

  def stop(self):
    if self.started:
      utils.stop_standing_subprocess(self.iperf_process)
      self.started = False
