# 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.

"""Script to generate a DLC (Downloadable Content) artifact."""

import logging

from chromite.lib import commandline
from chromite.lib import dlc_lib


def GetParser():
  """Creates an argument parser and returns it."""
  parser = commandline.ArgumentParser(description=__doc__)
  # This script is used both for building an individual DLC or copying all final
  # DLCs images to their final destination nearby chromiumos_test_image.bin,
  # etc. These two arguments are required in both cases.
  parser.add_argument(
      '--sysroot',
      type='path',
      metavar='DIR',
      help="The root path to the board's build root, e.g. "
      '/build/eve')
  # TODO(andrewlassalle): Remove src-dir in the future(2021?) if nobody uses it.
  parser.add_argument(
      '--src-dir',
      type='path',
      metavar='SRC_DIR_PATH',
      help='Override the default Root directory path that contains all DLC '
           'files to be packed.')
  parser.add_argument(
      '--install-root-dir',
      type='path',
      metavar='DIR',
      help='If building a specific DLC, it is the root path to'
      ' install DLC images (%s) and metadata (%s). Otherwise it'
      ' is the target directory where the Chrome OS images gets'
      ' dropped in build_image, e.g. '
      'src/build/images/<board>/latest.' % (dlc_lib.DLC_BUILD_DIR,
                                            dlc_lib.DLC_META_DIR))

  one_dlc = parser.add_argument_group('Arguments required for building only '
                                      'one DLC')
  one_dlc.add_argument(
      '--rootfs',
      type='path',
      metavar='ROOT_FS_PATH',
      help='Path to the platform rootfs.')
  one_dlc.add_argument(
      '--stateful',
      type='path',
      metavar='STATEFUL_PATH',
      help='Path to the platform stateful.')
  one_dlc.add_argument(
      '--pre-allocated-blocks',
      type=int,
      metavar='PREALLOCATEDBLOCKS',
      help='Number of blocks (block size is 4k) that need to'
      'be pre-allocated on device.')
  one_dlc.add_argument('--version', metavar='VERSION', help='DLC Version.')
  one_dlc.add_argument('--id', metavar='ID', help='DLC ID (unique per DLC).')
  one_dlc.add_argument(
      '--package',
      metavar='PACKAGE',
      help='The package ID that is unique within a DLC, One'
      ' DLC cannot have duplicate package IDs.')
  one_dlc.add_argument(
      '--name', metavar='NAME', help='A human-readable name for the DLC.')
  one_dlc.add_argument(
      '--description',
      help='The description for the DLC.')
  one_dlc.add_argument(
      '--board', metavar='BOARD', help='The target board we are building for.')
  one_dlc.add_argument('--fullnamerev', metavar='FULL_NAME_REV',
                       help='The full ebuild package name.')
  one_dlc.add_argument(
      '--fs-type',
      metavar='FS_TYPE',
      default=dlc_lib.SQUASHFS_TYPE,
      choices=(dlc_lib.SQUASHFS_TYPE, dlc_lib.EXT4_TYPE),
      help='File system type of the image.')
  one_dlc.add_argument(
      '--preload',
      default=False,
      action='store_true',
      help='Allow preloading of DLC.')
  one_dlc.add_argument(
      '--factory-install',
      default=False,
      action='store_true',
      help='Allow factory installing of DLC.')
  one_dlc.add_argument(
      '--used-by', default=dlc_lib.USED_BY_SYSTEM,
      choices=(dlc_lib.USED_BY_USER, dlc_lib.USED_BY_SYSTEM),
      help='Defines how this DLC will be used so dlcservice can take proper '
      'actions based on the type of usage. For example, if "user" is passed, '
      'dlcservice does ref counting when DLC is installed/uninstalled. For '
      '"system", there will be no such provisions.')
  one_dlc.add_argument(
      '--days-to-purge',
      type=int,
      default=0,
      help='Defines the number of days before purging a DLC after it has '
      'been uninstalled.')
  one_dlc.add_argument(
      '--mount-file-required',
      default=False,
      action='store_true',
      help='Allow indirect mount file generation for DLC.')
  one_dlc.add_argument(
      '--build-package',
      default=False,
      action='store_true',
      help='Flag to indicate if the script is executed during the '
           'build_packages phase.')
  return parser


def ValidateArguments(parser, opts, req_flags, invalid_flags):
  """Validates the correctness of the passed arguments.

  Args:
    parser: Arguments parser.
    opts: Parsed arguments.
    req_flags: all the required flags.
    invalid_flags: all the flags that are not allowed.
  """
  # Make sure if the intention is to build one DLC, all the required arguments
  # are passed and none of the invalid ones are passed. This will ensure the
  # script is called twice per DLC.
  if opts.id:
    if not all(vars(opts)[x] is not None for x in req_flags):
      parser.error('If the intention is to build only one DLC, all the flags'
                   '%s required for it should be passed.' % req_flags)
    if any(vars(opts)[x] is not None for x in invalid_flags):
      parser.error('If the intention is to build only one DLC, all the flags'
                   '%s should be passed in the build_packages phase, not in '
                   'the build_image phase.' % invalid_flags)

  if opts.fs_type == dlc_lib.EXT4_TYPE:
    parser.error('ext4 unsupported for DLC, see https://crbug.com/890060')

  if opts.id:
    dlc_lib.ValidateDlcIdentifier(opts.id)
  if opts.package:
    dlc_lib.ValidateDlcIdentifier(opts.package)


def main(argv):
  parser = GetParser()
  opts = parser.parse_args(argv)
  opts.Freeze()
  per_dlc_req_args = ['id']
  per_dlc_invalid_args = []
  if opts.build_package:
    per_dlc_req_args += ['pre_allocated_blocks', 'version', 'name',
                         'description', 'package', 'install_root_dir',
                         'days_to_purge']
    per_dlc_invalid_args += ['src_dir', 'sysroot', 'stateful']
  else:
    per_dlc_req_args += ['sysroot', 'board']
    per_dlc_invalid_args += ['name', 'pre_allocated_blocks', 'version',
                             'package', 'days_to_purge']

  ValidateArguments(parser, opts, per_dlc_req_args, per_dlc_invalid_args)

  if opts.build_package:
    logging.info('Building package: DLC %s', opts.id)
    params = dlc_lib.EbuildParams(
        dlc_id=opts.id,
        dlc_package=opts.package,
        fs_type=opts.fs_type,
        name=opts.name,
        description=opts.description,
        pre_allocated_blocks=opts.pre_allocated_blocks,
        version=opts.version,
        preload=opts.preload,
        factory_install=opts.factory_install,
        mount_file_required=opts.mount_file_required,
        used_by=opts.used_by,
        days_to_purge=opts.days_to_purge,
        fullnamerev=opts.fullnamerev)
    params.StoreDlcParameters(install_root_dir=opts.install_root_dir, sudo=True)

  else:
    dlc_lib.InstallDlcImages(
        sysroot=opts.sysroot,
        dlc_id=opts.id,
        install_root_dir=opts.install_root_dir,
        preload=opts.preload,
        factory_install=opts.factory_install,
        src_dir=opts.src_dir,
        rootfs=opts.rootfs,
        stateful=opts.stateful,
        board=opts.board)
