# Copyright 2019 The ChromiumOS Authors
# 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.
"""

import argparse
import json
import logging
import re

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 gs


GSC_PRODUCTION_JOB = "chromeos/release/sign-image"
GSC_STAGING_JOB = "chromeos/staging/staging-sign-image"
_IMAGE_TYPE = "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
        ) -> 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", dryrun=True
    )

    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(
        "--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(dryrun, builder, properties) -> None:
    """Launch one build.

    Args:
        dryrun: 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 dryrun:
        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 == "nightly"
        and options.keyset != "ti50-accessory-nodelocked-ro-premp"
    ):
        logging.error("--target nightly can only be built for node locked ros")
        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 = 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.dryrun, builder, properties)
    else:
        for dev in options.dev_ids:
            properties["gsc_instructions"]["device_id"] = dev
            LaunchOne(options.dryrun, builder, properties)
    return 0
