# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


from recipe_engine import recipe_api

import default
import ntpath
import ssh
import subprocess  # TODO(borenet): No! Remove this.


"""Win SSH flavor, used for running code on Windows via an SSH connection.

Copied from chromebook.py and modified for Windows.
"""


class WinSSHFlavor(ssh.SSHFlavor):

  def __init__(self, m):
    super(WinSSHFlavor, self).__init__(m)
    self.remote_homedir = 'C:\\Users\\chrome-bot\\botdata\\'
    self.device_dirs = default.DeviceDirs(
      bin_dir       = self.device_path_join(self.remote_homedir, 'bin'),
      dm_dir        = self.device_path_join(self.remote_homedir, 'dm_out'),
      perf_data_dir = self.device_path_join(self.remote_homedir, 'perf'),
      resource_dir  = self.device_path_join(self.remote_homedir, 'resources'),
      images_dir    = self.device_path_join(self.remote_homedir, 'images'),
      lotties_dir   = self.device_path_join(self.remote_homedir, 'lotties'),
      skp_dir       = self.device_path_join(self.remote_homedir, 'skps'),
      svg_dir       = self.device_path_join(self.remote_homedir, 'svgs'),
      mskp_dir      = self.device_path_join(self.remote_homedir, 'mskp'),
      tmp_dir       = self.remote_homedir)
    self._empty_dir = self.device_path_join(self.remote_homedir, 'empty')


  def _cmd(self, title, cmd, infra_step=True, fail_errorlevel=1, **kwargs):
    return self.m.run(self.m.python, title,
                      script=self.module.resource('win_ssh_cmd.py'),
                      args=[self.user_ip, cmd, fail_errorlevel],
                      infra_step=infra_step, **kwargs)

  def ensure_device_dir(self, path):
    self._cmd('mkdir %s' % path, 'if not exist "%s" md "%s"' % (path, path))

  def _rmdir(self, path):
    self._cmd('rmdir %s' % path, 'if exist "%s" rd "%s"' % (path, path))

  def device_path_join(self, *args):
    return ntpath.join(*args)

  def install(self):
    super(WinSSHFlavor, self).install()

    # Ensure that our empty dir is actually empty.
    self._rmdir(self._empty_dir)
    self.ensure_device_dir(self._empty_dir)

    self.create_clean_device_dir(self.device_dirs.bin_dir)

  def create_clean_device_dir(self, path):
    # Based on https://stackoverflow.com/a/98069 and
    # https://superuser.com/a/346112.
    self._cmd('clean %s' % path,
              'robocopy /mir "%s" "%s"' % (self._empty_dir, path),
              fail_errorlevel=8)

  def read_file_on_device(self, path, **kwargs):
    with self.m.step.nest('read %s' % path):
      tmp = self.m.path.mkdtemp('read_file_on_device')
      host_path = tmp.join(ntpath.basename(path))
      device_path = self.scp_device_path(path)
      ok = self._run('scp %s %s' % (device_path, host_path),
                     cmd=['scp', device_path, host_path],
                     infra_step=True, **kwargs)
      # TODO(dogben): Should readfile respect fail_build_on_failure and
      # abort_on_failure?
      if ok:
        return self.m.run.readfile(host_path)

  def remove_file_on_device(self, path):
    self._cmd('rm %s' % path, 'if exist "%s" del "%s"' % (path, path))

  def _copy_dir(self, src, dest):
    self._run('scp -r %s %s' % (src, dest),
              cmd=['scp', '-r', src, dest], infra_step=True)

  def copy_directory_contents_to_device(self, host_path, device_path):
    # Callers expect that the destination directory is replaced, which is not
    # how scp works when the destination is a directory. Instead scp to tmp_dir
    # and then robocopy to the correct destination.
    # Other flavors use a glob and subprocess with shell=True to copy the
    # contents of host_path; however, there are a lot of ways POSIX shell
    # interpretation could mess up Windows path names.
    with self.m.step.nest('copy %s to device' % host_path):
      tmp_pardir = self.device_path_join(
          self.device_dirs.tmp_dir,
          'tmp_copy_directory_contents_to_device')
      self.create_clean_device_dir(tmp_pardir)
      tmpdir = self.device_path_join(tmp_pardir,
                                     self.m.path.basename(host_path))
      self._copy_dir(host_path, self.scp_device_path(tmpdir))
      self._cmd('copy %s to %s' % (tmpdir, device_path),
                'robocopy /mir "%s" "%s"' % (tmpdir, device_path),
                fail_errorlevel=8)

  def copy_directory_contents_to_host(self, device_path, host_path):
    # Note that the glob in src is interpreted by the remote shell.
    src = self.scp_device_path(self.device_path_join(device_path, '*'))
    self._copy_dir(src, host_path)

  def step(self, name, cmd, infra_step=False, **kwargs):
    # There may be DLLs in the same dir as the executable that must be loaded
    # (yes, Windows allows overriding system DLLs with files in the local
    # directory). For simplicity, just copy the entire dir to the device.
    self.copy_directory_contents_to_device(self.host_dirs.bin_dir,
                                           self.device_dirs.bin_dir)
    device_bin = self.device_path_join(self.device_dirs.bin_dir, cmd[0])

    # Copy PowerShell script to device.
    ps = 'win_run_and_check_log.ps1'
    device_ps = self.device_path_join(self.device_dirs.bin_dir, ps)
    self.copy_file_to_device(self.module.resource(ps), device_ps)

    cmd = ['powershell', '-ExecutionPolicy', 'Unrestricted', '-File', device_ps,
           device_bin] + cmd[1:]
    self._cmd(name, subprocess.list2cmdline(map(str, cmd)),
              infra_step=infra_step, **kwargs)
