# Copyright 2020 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 attr

from recipe_engine import recipe_api
from recipe_engine.config_types import Path

_SSH_CONFIG_TEMPLATE = """
Host *
  CheckHostIP no
  StrictHostKeyChecking no
  ForwardAgent no
  ForwardX11 no
  UserKnownHostsFile /dev/null
  User fuchsia
  IdentitiesOnly yes
  IdentityFile {identity}
  ServerAliveInterval 2
  ServerAliveCountMax 5
  ControlMaster auto
  ControlPersist 1m
  ControlPath /tmp/ssh-%r@%h:%p
  ConnectTimeout 5
"""


@attr.s
class SSHFilePaths(object):
  """Required files to setup SSH on FEMU."""

  # Recipe API, required
  _api = attr.ib(type=recipe_api.RecipeApi)

  # Files for SSH
  host_private = attr.ib(type=Path, default=None)
  host_public = attr.ib(type=Path, default=None)

  id_private = attr.ib(type=Path, default=None)
  id_public = attr.ib(type=Path, default=None)

  def _exists(self, p):
    return p and self._api.path.exists(p)

  def _exist(self):
    return all([
        self._exists(self.host_private),
        self._exists(self.host_public),
        self._exists(self.id_private),
        self._exists(self.id_public),
    ])

  def _report_missing(self):
    result = []
    if not self._exists(self.host_private):
      result.append(self.host_private)
    if not self._exists(self.host_public):
      result.append(self.host_public)
    if not self._exists(self.id_private):
      result.append(self.id_private)
    if not self._exists(self.id_public):
      result.append(self.id_public)
    return result


class SSHApi(recipe_api.RecipeApi):

  def __init__(self, *args, **kwargs):
    super(SSHApi, self).__init__(*args, **kwargs)
    self._ssh_paths = None

  def _create_ssh_keys(self, timeout_secs=10 * 60):
    """Generate private, public key-pairs for Host side and Device side ssh keys."""
    self.m.file.ensure_directory('init ssh cache', self.ssh_cache_root)
    if not self._ssh_paths:
      self._ssh_paths = SSHFilePaths(
          api=self.m,
          host_private=self.ssh_cache_root.join('ssh_host_key'),
          host_public=self.ssh_cache_root.join('ssh_host_key.pub'),
          id_private=self.ssh_cache_root.join('id_ed25519'),
          id_public=self.ssh_cache_root.join('id_ed25519.pub'),
      )

    if not self.m.file.listdir(name='check ssh cache content',
                               source=self.ssh_cache_root, test_data=()):
      self.m.step(
          'ssh-keygen host',
          [
              'ssh-keygen',
              '-t',
              'ed25519',
              '-h',
              '-f',
              self._ssh_paths.host_private,
              '-P',
              '',
              '-N',
              '',
          ],
          infra_step=True,
          timeout=timeout_secs,
      )
      self.m.step(
          'ssh-keygen device',
          [
              'ssh-keygen',
              '-t',
              'ed25519',
              '-f',
              self._ssh_paths.id_private,
              '-P',
              '',
              '-N',
              '',
          ],
          infra_step=True,
          timeout=timeout_secs,
      )
    return self._ssh_paths

  def generate_ssh_config(self, private_key_path, dest):
    """Generates and sets the private_key_path in ssh_config file."""
    self.m.file.write_text(
        name='generate ssh_config at %s' % dest,
        dest=dest,
        text_data=_SSH_CONFIG_TEMPLATE.format(identity=private_key_path),
    )

  @property
  def ssh_paths(self):
    """Generate SSH keys.

    Raises:
      StepFailure: When ssh key file paths do not exist.
    """
    self._create_ssh_keys()
    if not self._ssh_paths._exist():
      missing = self._ssh_paths._report_missing()
      ex = self.m.step.StepFailure(
          'SSH paths do not exist. {missing_paths}'.format(
              missing_paths=missing
          )
      )
      ex.missing_paths = missing
      raise ex
    return self._ssh_paths

  @property
  def ssh_cache_root(self):
    return self.m.buildbucket.builder_cache_path.join('ssh')
