# -*- coding: utf-8 -*-
# Copyright 2019 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.

"""Trigger signing for cr50 images.

Causes signing to occur for a given artifact.
"""

from __future__ import print_function

import argparse
import json
import re
import sys

from chromite.api.gen.chromiumos import common_pb2
from chromite.api.gen.chromiumos import sign_image_pb2
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import gs


assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'


CR50_PRODUCTION_JOB = 'chromeos/packaging/sign-image'
CR50_STAGING_JOB = 'chromeos/staging/staging-sign-image'

# See ../infra/proto/src/chromiumos/common.proto.
_channels = {k.lower().replace('channel_', ''): v
             for k, v in common_pb2.Channel.items()}

# See ../infra/proto/src/chromiumos/common.proto.
_image_types = {k.lower(): v for k, v in common_pb2.ImageType.items() if v}

# See ../infra/proto/src/chromiumos/sign_image.proto.
_signer_types = {k.lower().replace('signer_', ''): v
                 for k, v in sign_image_pb2.SignerType.items() if v}

# See ../infra/proto/src/chromiumos/sign_image.proto.
_target_types = {k.lower(): v
                 for k, v in sign_image_pb2.Cr50Instructions.Target.items()
                 if v}


def GetParser():
  """Creates the argparse parser."""
  class uint32(int):
    """Unsigned 32-bit int."""
    def __new__(cls, val):
      """Return a positive 32-bit value."""
      return int(val, 0) & 0xffffffff

  class Dev01Action(argparse.Action):
    """Convert --dev01 MMM NNN into an %08x-%08x device_id."""
    def __call__(self, parser, namespace, values, option_string=None):
      if not namespace.dev_ids:
        namespace.dev_ids = []
      namespace.dev_ids.append('%08x-%08x' % (values[0], values[1]))

  parser = commandline.ArgumentParser(
      description=__doc__,
      default_log_level='debug')

  parser.add_argument(
      '--staging', action='store_true', dest='staging',
      help='Use the staging instance to create the request.')

  parser.add_argument(
      '--build-target', default='unknown', help='The build target.')

  parser.add_argument(
      '--channel', choices=_channels, default='unspecified',
      help='The (optional) channel for the artifact.')

  parser.add_argument(
      '--archive', required=True,
      help='The gs://path of the archive to sign.')

  parser.add_argument(
      '--dry-run', action='store_true', default=False,
      help='This is a dryrun, nothing will be triggered.')

  parser.add_argument(
      '--keyset', default='cr50-accessory-mp', help='The keyset to use.')

  parser.add_argument(
      '--image-type', choices=_image_types, default='cr50_firmware',
      help='The image type.')

  parser.add_argument(
      '--signer-type', choices=_signer_types,
      default='production', help='The image type.')

  parser.add_argument(
      '--target', choices=_target_types,
      default='prepvt', help='The image type.')

  node_locked = parser.add_argument_group(
      'Node_locked',
      description='Additional arguments for --target=node_locked')

  node_locked.add_argument(
      '--device-id', action='append', dest='dev_ids',
      help='The device_id ("%%08x-%%08x" format).')

  node_locked.add_argument(
      '--dev01', nargs=2, type=uint32, action=Dev01Action, metavar='DEVx',
      dest='dev_ids', help='DEV0 and DEV1 for the device')

  return parser


def LaunchOne(dry_run, builder, properties):
  """Launch one build.

  Args:
    dry_run: If true, just echo what would be done.
    builder: builder to use.
    properties: json properties to use.
  """
  json_prop = json.dumps(properties)
  cmd = ['bb', 'add', '-p', '@/dev/stdin', builder]
  if dry_run:
    logging.info('Would run: %s with input: %s', ' '.join(cmd), json_prop)
  else:
    cros_build_lib.run(cmd, input=json_prop, log_output=True)


def main(argv):
  parser = GetParser()
  options = parser.parse_args(argv)
  options.Freeze()

  passes = True
  if options.image_type != 'cr50_firmware':
    logging.error('Unsupported --image-type %s', options.image_type)
    passes = False

  if options.target == 'node_locked':
    if not options.dev_ids:
      logging.error('--target node_locked must specify device_id')
      passes = False
    else:
      for dev in options.dev_ids:
        if not re.match('[0-9a-fA-F]{8}-[0-9a-fA-F]{8}$', dev):
          logging.error('Illegal device_id %s', dev)
          passes = False
  elif options.dev_ids:
    logging.error('Device IDs are only valid with `--target node_locked`')
    passes = False

  if not passes:
    return 1

  builder = CR50_STAGING_JOB if options.staging else CR50_PRODUCTION_JOB

  properties = {
      'archive': options.archive,
      'build_target': {'name': options.build_target},
      'channel': _channels[options.channel],
      'cr50_instructions': {
          'target': _target_types[options.target],
      },
      'image_type': _image_types[options.image_type],
      'keyset': options.keyset,
      'signer_type': _signer_types[options.signer_type],
  }

  gcs = gs.GSContext()
  if not gcs.Exists(options.archive):
    logging.error('The archive %s was not found on google storage.',
                  options.archive)
    return 1

  if options.target != 'node_locked':
    LaunchOne(options.dry_run, builder, properties)
  else:
    for dev in options.dev_ids:
      properties['cr50_instructions']['device_id'] = dev
      LaunchOne(options.dry_run, builder, properties)
  return 0
