# -*- 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 gsc 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+'


GSC_PRODUCTION_JOB = 'chromeos/release/sign-image'
GSC_STAGING_JOB = 'chromeos/staging/staging-sign-image'
_IMAGE_TYPE = 'gsc_firmware'

# 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.GscInstructions.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(
      '--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.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 = GSC_STAGING_JOB if options.staging else GSC_PRODUCTION_JOB

  properties = {
      'archive': options.archive,
      'build_target': {'name': options.build_target},
      'channel': _channels[options.channel],
      'gsc_instructions': {
          'target': _target_types[options.target],
      },
      'image_type': _image_types[_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['gsc_instructions']['device_id'] = dev
      LaunchOne(options.dry_run, builder, properties)
  return 0
