# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Base impl of the Chrome OS Configuration access library."""

from __future__ import print_function

from collections import namedtuple, OrderedDict

import os

from cros_config_schema import GetValidSchemaProperties

# Defines a list of undiffable properties between the device-tree impl and
# the YAML based impl.  These properties are accounted for in other API level
# diffs, but they changed between the schemas and therefore can't be diffed.
INCOMPATIBLE_PROPERTIES = {
  '/' : [
    'brand-code',         # Moved due to Whitelabel/Product changes.
    'name',               # Only in YAML
  ],
  '/firmware' : [
    'key-id',             # Moved to firmware-signing in YAML,
    'name',               # Doesn't exist in DT impl
  ],
  '/firmware-signing' : [
    'key-id',             # Moved from firmware in DT
    'signature-id',       # Only in YAML
  ],
}

# Represents a single touch firmware file which needs to be installed:
#   source: source filename of firmware file. This is installed in a
#       directory in the root filesystem
#   dest: destination filename of firmware file in the root filesystem. This is
#       in /opt/google/touch/firmware
#   symlink: name of symbolic link to put in LIB_FIRMWARE to point to the touch
#       firmware. This is where Linux finds the firmware at runtime.
TouchFile = namedtuple('TouchFile', ['source', 'dest', 'symlink'])

# Represents a single file which needs to be installed:
#   source: Source filename within ${FILESDIR}
#   dest: Destination filename in the root filesystem
BaseFile = namedtuple('BaseFile', ['source', 'dest'])

# Represents information needed to create firmware for a model:
#   model: Name of model (e.g 'reef'). Also used as the signature ID for signing
#   shared_model: Name of model containing the shared firmware used by this
#       model, or None if this model has its own firmware images
#   key_id: Key ID used to sign firmware for this model (e.g. 'REEF')
#   have_image: True if we need to generate a setvars.sh file for this model.
#       If this is False it indicates that the model will never be detected at
#       run-time since it is a zero-touch whitelabel model. The signature ID
#       will be obtained from the customization_id in VPD when needed. Signing
#       instructions should still be generated for this model.
#   bios_build_target: Build target to use to build the BIOS, or None if none
#   ec_build_target: Build target to use to build the EC, or None if none
#   main_image_uri: URI to use to obtain main firmware image (e.g.
#       'bcs://Caroline.2017.21.1.tbz2')
#   ec_image_uri: URI to use to obtain the EC (Embedded Controller) firmware
#       image
#   pd_image_uri: URI to use to obtain the PD (Power Delivery controller)
#       firmware image
#   sig_id: Signature ID to put in the setvars.sh file. This is normally the
#       same as the model, since that is what we use for signature ID. But for
#       zero-touch whitelabel this is 'sig-id-in-customization-id' since we do
#       not know the signature ID until we look up in VPD.
#   brand-code: Uniquely identifies a given brand (see go/chromeos-rlz)
FirmwareInfo = namedtuple('FirmwareInfo', [
    'model', 'shared_model', 'key_id', 'have_image', 'bios_build_target',
    'ec_build_target', 'main_image_uri', 'main_rw_image_uri', 'ec_image_uri',
    'pd_image_uri', 'sig_id', 'brand_code'
])

class PathComponent(object):
  """A component in a directory/file tree

  Properties:
    name: Name this component
    children: Dict of children:
      key: Name of child
      value: PathComponent object for child
  """

  def __init__(self, name):
    self.name = name
    self.children = dict()

  def AddPath(self, path):
    parts = path.split('/', 1)
    part = parts[0]
    rest = parts[1] if len(parts) > 1 else ''
    child = self.children.get(part)
    if not child:
      child = PathComponent(part)
      self.children[part] = child
    if rest:
      child.AddPath(rest)

  def ShowTree(self, base_path, path='', indent=0):
    """Show a tree of file paths

    This shows a component and all its children. Nodes can either be directories
    or files. Each file is shown with its size, or 'missing' if not found.

    Args:
      base_path: Base path where the actual files can be found
      path: Path of this component relative to the root (e.g. 'etc/cras/)
      indent: Indent level we are up to (0 = first)
    """
    path = os.path.join(path, self.name)
    fname = os.path.join(base_path, path)
    if os.path.isdir(fname):
      status = ''
    elif os.path.exists(fname):
      status = os.stat(fname).st_size
    else:
      status = 'missing'
    print('%-10s%s%s%s' % (status, '   ' * indent, str(self.name),
                           self.children and '/' or ''))
    for child in sorted(self.children.keys()):
      self.children[child].ShowTree(base_path, path, indent + 1)


class DeviceConfig(object):
  """Configuration for a unique Device/SKU/Product combination.

  Provides an abstraction layer between DTS/JSON for accessing config for a
  unique Device/SKU/Product instance.
  """

  def GetName(self):
    """Returns the name of the config.

    Returns:
      Name of he config
    """
    pass

  def GetProperties(self, path):
    """Returns a map of properties at the given config path.

    Args:
      path: Path to the config desired.

    Returns:
      A map of properties at the given config path.
    """
    pass

  def GetProperty(self, path, name):
    """Returns the name value at a given path.

    Args:
      path: Path to the config desired.
      name: Property desired.

    Returns:
      Requested value or empty string if not present.
    """
    pass

  def GetFirmwareConfig(self):
    """Returns a map hierarchy of the firmware config."""
    pass

  def GetFirmwareUris(self):
    """Returns a list of (string) firmware URIs.

    Generates and returns a list of firmeware URIs for this device. These URIs
    can be used to pull down remote firmware packages.

    Returns:
      A list of (string) full firmware URIs, or an empty list on failure.
    """
    firmware = self.GetFirmwareConfig()
    if not firmware:
      return []

    if 'bcs-overlay' not in firmware:
      return []
    # Strip "overlay-" from bcs_overlay
    bcs_overlay = firmware['bcs-overlay'][8:]
    ebuild_name = bcs_overlay.split('-')[0]
    valid_images = [p for n, p in firmware.iteritems()
                    if n.endswith('-image') and p.startswith('bcs://')]
    # Strip "bcs://" from bcs_from images (to get the file names only)
    file_names = [p[6:] for p in valid_images]
    uri_format = ('gs://chromeos-binaries/HOME/bcs-{bcs}/overlay-{bcs}/'
                  'chromeos-base/chromeos-firmware-{ebuild_name}/{fname}')
    uris = [uri_format.format(
        bcs=bcs_overlay,
        model=self.GetName(),
        fname=fname,
        ebuild_name=ebuild_name) for fname in file_names]
    return sorted(uris)

  def GetTouchFirmwareFiles(self):
    """Get a list of unique touch firmware files

    Returns:
      List of TouchFile objects representing the touch firmware referenced
        by this model
    """
    pass

  def GetArcFiles(self):
    """Get a list of arc++ files for this device

    Returns:
      List of BaseFile objects representing the arc++ files needed.
    """
    pass

  def GetAudioFiles(self):
    """Get a list of audio files

    Returns:
      List of BaseFile objects representing the audio files referenced
      by this device.
    """
    pass

  def GetBluetoothFiles(self):
    """Get a list of bluetooth config files

    Returns:
      List of BaseFile objects representing the bluetooth files referenced
      by this device.
    """
    pass

  def GetThermalFiles(self):
    """Get a list of thermal files

    Returns:
      List of BaseFile objects representing the thermal files referenced
      by this device.
    """
    pass

  def GetFirmwareInfo(self):
    """Gets the FirmewareInfo instance for a given device.

    Returns:
      Returns the FirmwareInfo instance.
    """
    pass

  def GetWallpaperFiles(self):
    """Get a set of wallpaper files used for this model"""
    pass


class CrosConfigBaseImpl(object):
  """The ChromeOS Configuration API for the host."""

  def GetConfig(self, name):
    """Gets a (DeviceConfig) instance by name.

    Returns:
      (DeviceConfig) instance if found, else None
    """
    for device in self.GetDeviceConfigs():
      if device.GetName() == name:
        return device
    return None

  def GetDeviceConfigs(self):
    """Returns a list of (DeviceConfig) instances.

    Returns:
      A list of (DeviceConfig) instances.
    """
    pass

  def GetFullConfig(self):
    """Returns a full dict of every config returned from every API.

    Returns:
      Dictionary that maps method call onto return config.
    """
    result = {}
    result['ListModels'] = self.GetModelList()
    result['GetFirmwareUris'] = self.GetFirmwareUris()
    result['GetTouchFirmwareFiles'] = self.GetTouchFirmwareFiles()
    result['GetArcFiles'] = self.GetArcFiles()
    result['GetAudioFiles'] = self.GetAudioFiles()
    bluetooth_files = self.GetBluetoothFiles()
    if bluetooth_files:
      result['GetBluetoothFiles'] = bluetooth_files
    result['GetThermalFiles'] = self.GetThermalFiles()
    result['GetFirmwareInfo'] = self.GetFirmwareInfo()
    for target in ['coreboot', 'ec']:
      result['GetFirmwareBuildTargets_%s' % target] = \
        self.GetFirmwareBuildTargets(target)
    result['GetFirmwareBuildCombinations'] = \
      self.GetFirmwareBuildCombinations(['coreboot', 'ec'])
    result['GetWallpaperFiles'] = self.GetWallpaperFiles()

    schema_properties = GetValidSchemaProperties()
    for device in self.GetDeviceConfigs():
      value_map = {}
      for path in schema_properties:
        for schema_property in schema_properties[path]:
          # Exclude incompatible properties for now until the migration
          # is done and we aren't trying to diff properties any longer.
          if schema_property not in INCOMPATIBLE_PROPERTIES.get(path, []):
            prop_value = device.GetProperty(path, schema_property)
            # Only dump populated values; this makes it so the config dumps
            # don't need to be updated when new schema attributes are added.
            if prop_value:
              value_map['%s::%s' % (path, schema_property)] = prop_value
      result['GetProperty_%s' % device.GetName()] = value_map
    return result


  def GetFirmwareUris(self):
    """Returns a list of (string) firmware URIs.

    Generates and returns a list of firmeware URIs for all device. These URIs
    can be used to pull down remote firmware packages.

    Returns:
      A list of (string) full firmware URIs, or an empty list on failure.
    """
    uris = set()
    for device in self.GetDeviceConfigs():
      uris.update(set(device.GetFirmwareUris()))
    return sorted(list(uris))

  def GetTouchFirmwareFiles(self):
    """Get a list of unique touch firmware files for all devices

    These files may come from ${FILESDIR} or from a tar file in BCS.

    Returns:
      List of TouchFile objects representing all the touch firmware referenced
      by all devices
    """
    file_set = set()
    for device in self.GetDeviceConfigs():
      for files in device.GetTouchFirmwareFiles():
        file_set.add(files)

    return sorted(file_set, key=lambda files: files.source)

  def GetBcsUri(self, overlay, path):
    """Form a valid BCS URI for downloading files.

    Args:
      overlay: Name of overlay (e.g. 'reef-private')
      path: Path to file in overlay (e.g. 'chromeos-base/'
        'chromeos-touch-firmware-reef/chromeos-touch-firmware-reef-1.0-r9.tbz2')

    Returns:
      Valid BCS URI to download from
    """
    if not overlay.startswith('overlay'):
      return None
    # Strip "overlay-" from bcs_overlay.
    bcs_overlay = overlay[8:]
    return (
        'gs://chromeos-binaries/HOME/bcs-%(bcs)s/overlay-%(bcs)s/%(path)s' % {
            'bcs': bcs_overlay,
            'path': path
        })

  def GetArcFiles(self):
    """Get a list of unique Arc++ files for all devices

    Returns:
      List of BaseFile objects representing all the arc++ files referenced
      by all devices
    """
    file_set = set()
    for device in self.GetDeviceConfigs():
      for files in device.GetArcFiles():
        file_set.add(files)

    return sorted(file_set, key=lambda files: files.source)

  def GetAudioFiles(self):
    """Get a list of unique audio files for all models

    Returns:
      List of BaseFile objects representing all the audio files referenced
      by all models
    """
    file_set = set()
    for device in self.GetDeviceConfigs():
      for files in device.GetAudioFiles():
        file_set.add(files)

    return sorted(file_set, key=lambda files: files.source)

  def GetBluetoothFiles(self):
    """Get a list of unique bluetooth files for all devices

    Returns:
      List of BaseFile objects representing all the bluetooth files referenced
      by all devices
    """
    file_set = set()
    for device in self.GetDeviceConfigs():
      for files in device.GetBluetoothFiles():
        file_set.add(files)

    return sorted(file_set, key=lambda files: files.source)

  def GetFirmwareBuildTargets(self, target_type):
    """Returns a list of all firmware build-targets of the given target type.

    Args:
      target_type: A string type for the build-targets to return

    Returns:
      A list of all build-targets of the given type, for all models.
    """
    firmware_filter = os.getenv('FW_NAME')
    build_targets = []
    for device in self.GetDeviceConfigs():
      device_targets = device.GetProperties('/firmware/build-targets')
      # Skip nodes with no build targets
      if not device_targets:
        continue

      # TODO(teravest): Add a name field and use here instead of coreboot.
      key = device_targets['coreboot']
      if firmware_filter and key != firmware_filter:
        continue
      if target_type in device_targets:
        build_targets.append(device_targets[target_type])
      if target_type == 'ec':
        for ec_extra in ('base', 'cr50'):
          if ec_extra in device_targets:
            build_targets.append(device_targets[ec_extra])
        if 'ec_extras' in device_targets:
          for extra_target in device_targets['ec_extras']:
            build_targets.append(extra_target)
    return sorted(set(build_targets))

  def GetFirmwareBuildCombinations(self, components):
    """Get named firmware build combinations for all devices.

    Args:
      components: List of firmware components to get target combinations for.

    Returns:
      OrderedDict containing firmware combinations
        key: combination name
        value: list of firmware targets for specified types

    Raises:
      ValueError if a collision is encountered for named combinations.
    """
    firmware_filter = os.getenv('FW_NAME')

    combos = OrderedDict()
    for device in self.GetDeviceConfigs():
      device_targets = device.GetProperties('/firmware/build-targets')
      # Skip device_targetss with no build targets
      if not device_targets:
        continue
      targets = [device_targets[c] for c in components if c in device_targets]

      # Always name firmware combinations after the 'coreboot' name.
      # TODO(teravest): Add a 'name' field.
      key = device_targets['coreboot']
      if firmware_filter and key != firmware_filter:
        continue

      if key in combos and targets != combos[key]:
        raise ValueError('Colliding firmware combinations found for key %s: '
                         '%s, %s' % (key, targets, combos[key]))
      combos[key] = targets
    return OrderedDict(sorted(combos.iteritems()))

  def GetThermalFiles(self):
    """Get a list of unique thermal files for all models

    Returns:
      List of BaseFile objects representing all the audio files referenced
      by all devices
    """
    file_set = set()
    for device in self.GetDeviceConfigs():
      for files in device.GetThermalFiles():
        file_set.add(files)

    return sorted(file_set, key=lambda files: files.source)

  def ShowTree(self, base_path, tree):
    print('%-10s%s' % ('Size', 'Path'))
    tree.ShowTree(base_path)

  def GetFileTree(self):
    """Get a tree of all files installed by the config

    This looks at all available config that installs files in the root and
    returns them as a tree structure. This can be passed to ShowTree(), which
    is the only feature currently implemented which uses this tree.

    Returns:
        PathComponent object containing the root component
    """
    paths = set()
    for item in self.GetAudioFiles():
      paths.add(item.dest)
    for item in self.GetTouchFirmwareFiles():
      paths.add(item.dest)
      paths.add(item.symlink)
    root = PathComponent('')
    for path in paths:
      root.AddPath(path[1:])

    return root

  def GetModelList(self):
    """Return a list of models

    Returns:
      List of model names, each a string
    """
    return sorted(set([device.GetName() for device in self.GetDeviceConfigs()]))

  def GetFirmwareInfo(self):
    firmware_info = OrderedDict()
    for name in self.GetModelList():
      for device in self.GetDeviceConfigs():
        if device.GetName() == name:
          firmware_info.update(device.GetFirmwareInfo())
    return firmware_info

  def GetWallpaperFiles(self):
    """Get a list of wallpaper files used for all models"""
    wallpapers = set()
    for device in self.GetDeviceConfigs():
      wallpapers |= device.GetWallpaperFiles()
    return sorted(wallpapers)
