#!/usr/bin/env python
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import glob
import os
import re
import shlex
import subprocess

from host import Host


class Device(object):
  """Represents a Fuchsia device attached to a host.

    This class abstracts the details of remotely running commands and
    transferring data to and from the device.

    Attributes:
      host: A Host object represent the local platform attached to this target
        device.
  """

  @classmethod
  def from_args(cls, host, args):
    """Constructs a Device from command line arguments."""
    netaddr_cmd = ['netaddr', '--fuchsia', '--nowait']
    default_device = '{}.device'.format(host.build_dir)
    if args.device:
      netaddr_cmd.append(args.device)
    elif os.path.exists(default_device):
      with open(default_device) as f:
        netaddr_cmd.append(f.read().strip())
    try:
      netaddr = host.zircon_tool(netaddr_cmd)
    except subprocess.CalledProcessError:
      raise RuntimeError('Unable to find device; try `fx set-device`.')
    device = cls(host, netaddr)
    if not host.build_dir:
      raise Host.ConfigError('Unable to find SSH configuration.')
    device.set_ssh_config(Host.join(host.build_dir, 'ssh-keys', 'ssh_config'))
    return device

  def __init__(self, host, addr, port=22):
    self.host = host
    self._addr = addr
    self._ssh_opts = {}
    if port != 22:
      self._ssh_opts['p'] = [str(port)]

  def set_ssh_config(self, config_file):
    """Sets the SSH arguments to use a config file."""
    if not os.path.exists(config_file):
      raise Host.ConfigError('Unable to find SSH configuration.')
    self._ssh_opts['F'] = [config_file]

  def set_ssh_identity(self, identity_file):
    if not os.path.exists(identity_file):
      raise Host.ConfigError('Unable to find SSH identity.')
    self._ssh_opts['i'] = [identity_file]

  def set_ssh_option(self, option):
    """Sets SSH configuration options. Can be used multiple times."""
    if 'o' in self._ssh_opts:
      self._ssh_opts['o'].append(option)
    else:
      self._ssh_opts['o'] = [option]

  def set_ssh_verbosity(self, level):
    """Sets how much debugging SSH prints. Default is 0 (none), max is 3."""
    for i in range(1, 4):
      opt = 'v' * i
      if level == i and not opt in self._ssh_opts:
        self._ssh_opts[opt] = []
      elif level != i and opt in self._ssh_opts:
        del self._ssh_opts[opt]

  def get_ssh_cmd(self, cmd):
    """Returns the SSH executable and options."""
    result = cmd[:1]
    for opt, args in self._ssh_opts.iteritems():
      if len(args) == 0:
        result.append('-' + opt)
      else:
        for arg in args:
          result.append('-' + opt)
          result.append(arg)
    return result + cmd[1:]

  def _ssh(self, cmdline, stdout=subprocess.PIPE):
    """Internal wrapper around _rexec that adds the ssh command and config.

    Don't call this directly. This method exists to be overridden in testing.

    Args:
      cmdline: List of command line arguments to execute on device
      stdout: Same as for subprocess.Popen

    Returns:
      If check was false, a subprocess.Popen object representing the running
      child process.

    Raises: Same as subprocess.Popen
    """
    return subprocess.Popen(
        self.get_ssh_cmd(['ssh', self._addr] + cmdline),
        stdout=stdout,
        stderr=subprocess.STDOUT)

  def ssh(self, cmdline, quiet=True, logfile=None):
    """Runs a command to completion on the device.

    Connects to the target device and executes a shell command.  Output from
    the shell command is sent to stdout, and may optionally be saved to a file
    via the POSIX utility 'tee'.

    Args:
      cmdline: A list of command line arguments, starting with the command to
        execute.
      logfile: An optional pathname to save a copy of the command output to. The
        output will also still be sent to stdout.
    """
    if quiet:
      if logfile:
        with open(logfile, 'w') as f:
          self._ssh(cmdline, stdout=f).wait()
      else:
        self._ssh(cmdline, stdout=Host.DEVNULL).wait()
    else:
      if logfile:
        proc = self._ssh(cmdline, stdout=subprocess.PIPE)
        subprocess.check_call(['tee', logfile], stdin=proc.stdout)
      else:
        self._ssh(cmdline, stdout=None).wait()

  def getpids(self):
    """Maps names to process IDs for running fuzzers.

    Connects to the device and checks which fuzz targets have a matching entry
    in the component list given by 'cs'.  This matches on *only* the first 32
    characters of the component manifest and package URL.  This is due to 'cs'
    being limited to returning strings of length `ZX_MAX_NAME_LEN`, as defined
    in //zircon/system/public/zircon/types.h.

    Returns:
      A dict mapping fuzz target names to process IDs. May be empty if no
      fuzzers are running.
    """
    out, _ = self._ssh(['cs'], stdout=subprocess.PIPE).communicate()
    pids = {}
    for fuzzer in self.host.fuzzers:
      tgt = (fuzzer[1] + '.cmx')[:32]
      url = ('fuchsia-pkg://fuchsia.com/%s#meta' % fuzzer[0])[:32]
      for line in str(out).split('\n'):
        match = re.search(tgt + r'\[(\d+)\]: ' + url, line)
        if match:
          pids[fuzzer[1]] = int(match.group(1))
    return pids

  def ls(self, path):
    """Maps file names to sizes for the given path.

    Connects to a Fuchsia device and lists the files in a directory given by
    the provided path.  Ignore non-existent paths.

    Args:
      path: Absolute path to a directory on the device.

    Returns:
      A dict mapping file names to file sizes, or an empty dict if the path
      does not exist.
    """
    results = {}
    try:
      out, _ = self._ssh(
          ['ls', '-l', path], stdout=subprocess.PIPE).communicate()
      for line in str(out).split('\n'):
        # Line ~= '-rw-r--r-- 1 0 0 8192 Mar 18 22:02 some-name'
        parts = line.split()
        if len(parts) > 8:
          results[' '.join(parts[8:])] = int(parts[4])
    except subprocess.CalledProcessError:
      pass
    return results

  def _scp(self, srcs, dst):
    """Copies `src` to `dst`.

    Don't call directly; use `fetch` or `store` instead.`

    Args:
      srcs: Local or remote paths to copy from.
      dst: Local or remote path to copy to.
    """
    # Wild cards only work if shell=True and the whole line passed as a string.
    cmd = self.get_ssh_cmd(['scp'] + srcs + [dst])
    subprocess.check_call(cmd, stdout=None, stderr=None)

  def fetch(self, data_src, host_dst):
    """Copies `data_src` on the target to `host_dst` on the host."""
    if not os.path.isdir(host_dst):
      raise ValueError(host_dst + ' is not a directory')
    self._scp(['[{}]:{}'.format(self._addr, data_src)], host_dst)

  def store(self, host_src, data_dst):
    """Copies `host_src` on the host to `data_dst` on the target."""
    self.ssh(['mkdir', '-p', data_dst])
    self._scp(glob.glob(host_src), '[{}]:{}'.format(self._addr, data_dst))
