# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import re
from enum import Enum

from recipe_engine import recipe_api


class BcidStage(Enum):
  """Enum representing valid bcis stages."""
  START = 'start'
  FETCH = 'fetch'
  COMPILE = 'compile'
  UPLOAD = 'upload'
  UPLOAD_COMPLETE = 'upload-complete'
  TEST = 'test'


VSA_EXTENSION = ".vsa.intoto.jsonl"


class FlutterBcidApi(recipe_api.RecipeApi):

  def is_official_build(self):
    bucket = self.m.buildbucket.build.builder.bucket
    # No-op for builders running outside of dart-internal.
    return bucket == 'flutter'

  def is_prod_build(self):
    bucket = self.m.buildbucket.build.builder.bucket
    return bucket == 'prod'

  def report_stage(self, stage):
    if self.is_official_build():
      self.m.bcid_reporter.report_stage(stage)

  def upload_provenance(self, local_artifact_path, remote_artifact_path):
    """Generate provenance for given artifact.

    This function acts on one specific local file and one specific remote file
    location. It does not accept glob patterns or directories. This method is a
    noop if it is not an official build, as only official builds generate
    provenance.

    parmeters:
      local_artifact_path: (str) path and filename of a specific file.
      remote_artifact_path: (str) path and filename of a specific file.
    """
    if self.is_official_build():
      sha256 = self.m.file.file_hash(local_artifact_path)
      self.m.bcid_reporter.report_gcs(sha256, remote_artifact_path)

  def download_and_verify_provenance(
      self, filename, bucket, gcs_path_without_bucket
  ):
    """Downloads and verifies provenance for a specified artifact.

    This method downloads an artifact and associated provenance from GCS,
    verifies it. If verification fails, an error is raised. This method is a
    noop if it is not an official build, as only official builds generate
    provenance.

    parameters:
      filename: (str) the name of the file, eg: "flutter_artifact.zip"
      bucket: (str) the GCS bucket, eg: "flutter_infra_release"
      gcs_path_without_bucket: (str) the GCS path, excluding gs://{bucket}/
        eg: "flutter/004d0bdf6721bc65cdb9a558908b2de4cfac97c5/sky_engine.zip"
    """
    if self.is_official_build():
      verify_temp_path = self.m.path.mkdtemp("verify")
      download_path = download_path = verify_temp_path.join(filename)
      bcid_response = self.m.dart.download_and_verify(
          filename, bucket, gcs_path_without_bucket, download_path,
          'misc_software://flutter/engine'
      )

      artifact_vsa = bcid_response['verificationSummary']
      vsa_local_path = f'{download_path}{VSA_EXTENSION}'
      self.m.file.write_text(
          f'write {filename}{VSA_EXTENSION}', vsa_local_path, artifact_vsa
      )
      vsa_path_without_bucket = gcs_path_without_bucket + VSA_EXTENSION
      self.m.gsutil.upload(
          vsa_local_path,
          bucket,
          vsa_path_without_bucket,
          name=f'upload "{vsa_path_without_bucket}"',
      )
