// Copyright 2019 The Flutter 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 'package:json_annotation/json_annotation.dart';

import '../../request_handling/body.dart';
import '../common/json_converters.dart';
import '../google/grpc.dart';

part 'buildbucket.g.dart';

// The classes in this file are based on protos found in:
// https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/build.proto
// https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/common.proto
// https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/rpc.proto
//
// The `fromJson` methods in this class are static rather than factories so that
// they can be passed as arguments to other functions looking for a parser.

/// A request for the Batch RPC.
///
/// This message can be used to find, get, schedule, or cancel multiple builds.
@JsonSerializable(includeIfNull: false)
class BatchRequest extends JsonBody {
  /// Creates a request for the Batch RPC.
  const BatchRequest({
    this.requests,
  });

  /// Creates a [BatchRequest] from JSON.
  static BatchRequest fromJson(Map<String, dynamic> json) => _$BatchRequestFromJson(json);

  /// The batch of [Request]s to make.
  final List<Request>? requests;

  @override
  Map<String, dynamic> toJson() => _$BatchRequestToJson(this);

  @override
  String toString() {
    return requests.toString();
  }
}

/// A container for one request in a batch.
///
/// A single request must contain only one object.
@JsonSerializable(includeIfNull: false)
class Request extends JsonBody {
  /// Creates a request for the Batch RPC.
  ///
  /// One and only one argument should be set.
  const Request({
    this.getBuild,
    this.searchBuilds,
    this.scheduleBuild,
    this.cancelBuild,
  }) : assert((getBuild != null && searchBuilds == null && scheduleBuild == null && cancelBuild == null) ||
            (getBuild == null && searchBuilds != null && scheduleBuild == null && cancelBuild == null) ||
            (getBuild == null && searchBuilds == null && scheduleBuild != null && cancelBuild == null) ||
            (getBuild == null && searchBuilds == null && scheduleBuild == null && cancelBuild != null));

  /// Creates a [Request] object from JSON.
  static Request fromJson(Map<String, dynamic> json) => _$RequestFromJson(json);

  /// A request to get build information.
  final GetBuildRequest? getBuild;

  /// A request to find builds.
  final SearchBuildsRequest? searchBuilds;

  /// A request to schedule a build.
  ///
  /// All schedule build requests are executed before other requests by LUCI.
  final ScheduleBuildRequest? scheduleBuild;

  /// A request to cancel a build.
  final CancelBuildRequest? cancelBuild;

  @override
  Map<String, dynamic> toJson() => _$RequestToJson(this);

  @override
  String toString() {
    return getBuild?.toString() ??
        searchBuilds?.toString() ??
        scheduleBuild?.toString() ??
        cancelBuild?.toString() ??
        'Unknown build';
  }
}

/// A response from the Batch RPC.
@JsonSerializable(includeIfNull: false)
class BatchResponse extends JsonBody {
  /// Creates a response for the Batch RPC.
  const BatchResponse({
    this.responses,
  });

  /// Creates a [BatchResponse] from JSON.
  static BatchResponse fromJson(Map<String, dynamic>? json) => _$BatchResponseFromJson(json!);

  /// The collected responses from the Batch request.
  final List<Response>? responses;

  @override
  Map<String, dynamic> toJson() => _$BatchResponseToJson(this);
}

/// An individual response from a batch request.
@JsonSerializable(includeIfNull: false)
class Response extends JsonBody {
  /// Creates a response for the response from the Batch RPC.
  ///
  /// One and only one of these should be set.
  const Response({
    this.getBuild,
    this.searchBuilds,
    this.scheduleBuild,
    this.cancelBuild,
    this.error,
  }) : assert(
            getBuild != null || searchBuilds != null || scheduleBuild != null || cancelBuild != null || error != null);

  /// Creates a [Response] from JSON.
  static Response fromJson(Map<String, dynamic> json) => _$ResponseFromJson(json);

  /// The [Build] response corresponding to a getBuild request.
  final Build? getBuild;

  /// The [SearchBuildsResponse] corresponding to a searchBuilds request.
  final SearchBuildsResponse? searchBuilds;

  /// The [Build] response corresponding to a scheduleBuild request.
  final Build? scheduleBuild;

  /// The [Build] response corresponding to a cancelBuild request.
  final Build? cancelBuild;

  /// Error code of the unsuccessful request.
  final GrpcStatus? error;

  @override
  String toString() {
    if (getBuild != null) {
      return 'getBuild: $getBuild; status: $error';
    } else if (searchBuilds != null) {
      return 'searchBuilds: $searchBuilds; status: $error';
    } else if (scheduleBuild != null) {
      return 'scheduleBuild: $scheduleBuild; status: $error';
    } else if (cancelBuild != null) {
      return 'cancelBuild: $cancelBuild; status: $error';
    }

    return 'No response';
  }

  @override
  Map<String, dynamic> toJson() => _$ResponseToJson(this);
}

/// A request for the GetBuild RPC.
@JsonSerializable(includeIfNull: false)
class GetBuildRequest extends JsonBody {
  /// Creates a request for the GetBuild RPC.
  const GetBuildRequest({
    this.id,
    this.builderId,
    this.buildNumber,
    this.fields,
  }) : assert((id == null && builderId != null && buildNumber != null) ||
            (id != null && builderId == null && buildNumber == null));

  /// Creates a [GetBuildRequest] from JSON.
  static GetBuildRequest fromJson(Map<String, dynamic> json) => _$GetBuildRequestFromJson(json);

  /// The BuildBucket build ID.
  ///
  /// If specified, [builderId] and [buildNumber] must be null.
  final String? id;

  /// The BuildBucket [BuilderId].
  ///
  /// If specified, [buildNumber] must be specified, and [id] must be null.
  @JsonKey(name: 'builder')
  final BuilderId? builderId;

  /// The BuildBucket build number.
  ///
  /// If specified, [builderId] must be specified, and [id] must be null.
  final int? buildNumber;

  /// The list fields to be included in the response.
  ///
  /// This is a comma separated list of Build proto fields to get included
  /// in the response.
  final String? fields;

  @override
  Map<String, dynamic> toJson() => _$GetBuildRequestToJson(this);

  @override
  String toString() {
    return 'getBuild(id: $id, buildNumber: $buildNumber, field: $fields, builderId: $builderId)';
  }
}

/// A request for the GetBuilder RPC.
@JsonSerializable(includeIfNull: false)
class GetBuilderRequest extends JsonBody {
  /// Creates a request for the GetBuild RPC.
  const GetBuilderRequest({
    this.builderId,
  }) : assert(builderId != null);

  /// Creates a [GetBuilderRequest] from JSON.
  static GetBuilderRequest fromJson(Map<String, dynamic> json) => _$GetBuilderRequestFromJson(json);

  /// The BuildBucket builder ID.
  final BuilderId? builderId;

  @override
  Map<String, dynamic> toJson() => _$GetBuilderRequestToJson(this);

  @override
  String toString() {
    return 'getBuild(builderId: $builderId)';
  }
}

/// Configs of a builder.
@JsonSerializable(includeIfNull: false)
class BuilderConfig extends JsonBody {
  /// Creates a request for the GetBuild RPC.
  const BuilderConfig({
    this.name,
  }) : assert(name != null);

  /// Creates a [GetBuilderRequest] from JSON.
  static BuilderConfig fromJson(Map<String, dynamic> json) => _$BuilderConfigFromJson(json);

  /// The BuildBucket builder ID.
  final String? name;

  @override
  Map<String, dynamic> toJson() => _$BuilderConfigToJson(this);

  @override
  String toString() {
    return 'BuilderConfig(name: $name)';
  }
}

/// A configured builder.
///
/// https://chromium.googlesource.com/infra/luci/luci-go/+/main/buildbucket/proto/builder_common.proto
@JsonSerializable(includeIfNull: false)
class BuilderItem extends JsonBody {
  /// Creates a request for the GetBuild RPC.
  const BuilderItem({
    this.id,
    this.config,
  });

  /// Creates a [GetBuilderRequest] from JSON.
  static BuilderItem fromJson(Map<String, dynamic>? json) => _$BuilderItemFromJson(json!);

  /// The BuildBucket builder ID.
  final BuilderId? id;

  /// The BuildBucket builder config.
  final BuilderConfig? config;

  @override
  Map<String, dynamic> toJson() => _$BuilderItemToJson(this);

  @override
  String toString() {
    return 'BuilderItem(builderID: $id, builderConfig: $config)';
  }
}

/// A requrst for the ListBuilders RPC.
@JsonSerializable(includeIfNull: false)
class ListBuildersRequest extends JsonBody {
  /// Creates a request object for the ListBuilders RPC.
  const ListBuildersRequest({
    required this.project,
    this.bucket,
    this.pageSize = 1000,
    this.pageToken,
  });

  /// Creates a [ListBuildersRequest] from JSON.
  static ListBuildersRequest fromJson(Map<String, dynamic> json) => _$ListBuildersRequestFromJson(json);

  /// LUCI project, e.g. "flutter".
  @JsonKey(required: true)
  final String project;

  /// A bucket in the project, e.g. "prod".
  ///
  /// Omit to list all builders or all builders in a project.
  @JsonKey(required: false)
  final String? bucket;

  /// The maximum number of builders to return.
  ///
  /// The service may return fewer than this value.
  /// If unspecified, at most 100 builders will be returned.
  /// The maximum value is 1000; values above 1000 will be coerced to 1000.
  @JsonKey(required: false)
  final int? pageSize;

  // A page token, received from a previous `ListBuilders` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListBuilders` MUST
  // match the call that provided the page token.
  @JsonKey(required: false)
  final String? pageToken;

  @override
  Map<String, dynamic> toJson() => _$ListBuildersRequestToJson(this);

  @override
  String toString() {
    return 'listBuilders(project: $project, bucket: $bucket, pageSize: $pageSize, pageToken: $pageToken)';
  }
}

/// The response object from a ListBuilders RPC.
@JsonSerializable(includeIfNull: false)
class ListBuildersResponse extends JsonBody {
  /// Creates a new response object from the ListBuilders RPC.
  ///
  /// The [nextPageToken] can be used to coninue searching if there are more
  /// builds available than the [pageSize] of the request (which is always
  /// capped at 1000). It will be null if no further builders are available.
  const ListBuildersResponse({
    this.builders,
    this.nextPageToken,
  });

  /// Creates a [ListBuildersResponse] from JSON.
  static ListBuildersResponse fromJson(Map<String, dynamic>? json) => _$ListBuildersResponseFromJson(json!);

  /// The [Builders]s returned by the search.
  final List<BuilderItem>? builders;

  /// A token that can be used as the [ListBuildersRequest.pageToken].
  ///
  /// This value will only be specified if further results are available;
  /// otherwise, it will be null.
  final String? nextPageToken;

  @override
  Map<String, dynamic> toJson() => _$ListBuildersResponseToJson(this);

  @override
  String toString() => builders.toString();
}

/// A request for the CancelBuild RPC.
@JsonSerializable(includeIfNull: false)
class CancelBuildRequest extends JsonBody {
  /// Creates a request object for the CancelBuild RPC.
  ///
  /// Both [id] and [summaryMarkdown] are required.
  const CancelBuildRequest({
    required this.id,
    required this.summaryMarkdown,
  });

  /// Creates a [CancelBuildRequest] from JSON.
  static CancelBuildRequest fromJson(Map<String, dynamic> json) => _$CancelBuildRequestFromJson(json);

  /// The BuildBucket ID for the build to cancel.
  @JsonKey(required: true)
  final String id;

  /// A summary of the reason for canceling.
  @JsonKey(required: true)
  final String summaryMarkdown;

  @override
  Map<String, dynamic> toJson() => _$CancelBuildRequestToJson(this);

  @override
  String toString() {
    return 'cancelBuild(id: $id, summaryMarkdown: $summaryMarkdown)';
  }
}

/// A request object for the SearchBuilds RPC.
@JsonSerializable(includeIfNull: false)
class SearchBuildsRequest extends JsonBody {
  /// Creates a request object for the SearchBuilds RPC.
  ///
  /// The [predicate] is required.
  ///
  /// The [pageSize] defaults to 100 if not specified.
  ///
  /// The [pageToken] from a previous request can be used to page through
  /// results.
  const SearchBuildsRequest({
    required this.predicate,
    this.pageSize,
    this.pageToken,
    this.fields,
  });

  /// Creates a [SearchBuildsReqeuest] object from JSON.
  static SearchBuildsRequest fromJson(Map<String, dynamic> json) => _$SearchBuildsRequestFromJson(json);

  /// The predicate for searching.
  final BuildPredicate predicate;

  /// The number of builds to return per request.  Defaults to 100.
  ///
  /// Any value over 1000 is treated as 1000.
  final int? pageSize;

  /// The value of the [SearchBuildsResponse.nextPageToken] from a previous ]
  /// request.
  ///
  /// This can be used to continue paging through results when there are more
  /// than [pageSize] builds available.
  final String? pageToken;

  /// The list fields to be included in the response.
  ///
  /// This is a comma separated list of Build proto fields to get included
  /// in the response.
  final String? fields;

  @override
  Map<String, dynamic> toJson() => _$SearchBuildsRequestToJson(this);

  @override
  String toString() {
    return 'searchBuild(predicate: $predicate, pageSize: $pageSize, pageToken: $pageToken, fields: $fields)';
  }
}

/// A predicate to apply when searching for builds in the SearchBuilds RPC.
@JsonSerializable(includeIfNull: false)
class BuildPredicate extends JsonBody {
  /// Creates a predicate to apply when searching for builds in the SearchBuilds
  /// RPC.
  ///
  /// All items specified must match for the predicate to return.
  const BuildPredicate({
    this.builderId,
    this.status,
    this.createdBy,
    this.tags,
    this.includeExperimental,
  });

  /// Creates a [BuildPredicate] from JSON.
  static BuildPredicate fromJson(Map<String, dynamic> json) => _$BuildPredicateFromJson(json);

  /// The [BuilderId] to search for.
  @JsonKey(name: 'builder')
  final BuilderId? builderId;

  /// The [Status] to search for.
  final Status? status;

  /// Used to find builds created by the specified user.
  final String? createdBy;

  /// Used to return builds containing all of the specified tags.
  @TagsConverter()
  final Map<String?, List<String?>>? tags;

  /// Determines whether to include experimental builds in the result.
  ///
  /// Defaults to false.
  final bool? includeExperimental;

  @override
  Map<String, dynamic> toJson() => _$BuildPredicateToJson(this);

  @override
  String toString() {
    return 'buildPredicate(builderId: $builderId, status: $status, createdBy: $createdBy, tags: $tags, includeExperimental: $includeExperimental)';
  }
}

/// The response object from a SearchBuilds RPC.
@JsonSerializable(includeIfNull: false)
class SearchBuildsResponse extends JsonBody {
  /// Creates a new response object from the SearchBuilds RPC.
  ///
  /// The [nextPageToken] can be used to coninue searching if there are more
  /// builds available than the [pageSize] of the request (which is always
  /// capped at 1000). It will be null if no further builds are available.
  const SearchBuildsResponse({
    this.builds,
    this.nextPageToken,
  });

  /// Creates a [SearchBuildsResponse] from JSON.
  static SearchBuildsResponse fromJson(Map<String, dynamic>? json) => _$SearchBuildsResponseFromJson(json!);

  /// The [Build]s returned by the search.
  final List<Build>? builds;

  /// A token that can be used as the [SearchBuildsRequest.pageToken].
  ///
  /// This value will only be specified if further results are available;
  /// otherwise, it will be null.
  final String? nextPageToken;

  @override
  Map<String, dynamic> toJson() => _$SearchBuildsResponseToJson(this);

  @override
  String toString() => builds.toString();
}

/// A request object for the ScheduleBuild RPC.
@JsonSerializable(includeIfNull: false)
class ScheduleBuildRequest extends JsonBody {
  /// Creates a new request object for the ScheduleBuild RPC.
  ///
  /// The [requestId] is "strongly recommended", and is used by the back end to
  /// deduplicate recent requests.
  ///
  /// The [builderId] is required.
  const ScheduleBuildRequest({
    this.requestId,
    required this.builderId,
    this.canary,
    this.experimental,
    this.gitilesCommit,
    this.properties,
    this.dimensions,
    this.priority,
    this.tags,
    this.notify,
    this.fields,
    this.exe,
  });

  /// Creates a [ScheduleBuildRequest] from JSON.
  static ScheduleBuildRequest fromJson(Map<String, dynamic> json) => _$ScheduleBuildRequestFromJson(json);

  /// A unique identifier per request that is used by the backend to deduplicate
  /// requests.
  ///
  /// This is "strongly recommended", but not required.
  final String? requestId;

  /// The [BuilderId] to schedule on. Required.
  @JsonKey(name: 'builder')
  final BuilderId builderId;

  /// If specified, overrides the server-defined value of
  /// Build.infra.buildbucket.canary.
  final bool? canary;

  /// If specified, overrides the server-defined value of
  /// Build.input.experimental.
  ///
  /// This value comes into the recipe as `api.runtime.is_experimental`.
  final Trinary? experimental;

  /// Properties to include in Build.input.properties.
  /// Input properties of the created build are result of merging server-defined
  /// properties and properties in this field.
  /// Each property in this field defines a new or replaces an existing property
  /// on the server.
  /// If the server config does not allow overriding/adding the property, the
  /// request will fail with InvalidArgument error code.
  /// A server-defined property cannot be removed, but its value can be
  /// replaced with null.
  ///
  /// Reserved property paths:
  /// * ["buildbucket"]
  /// * ["buildername"]
  /// * ["blamelist""]
  /// * ["$recipe_engine/runtime", "is_luci"]
  /// * ["$recipe_engine/runtime", "is_experimental"]
  final Map<String, dynamic>? properties;

  /// The value for Build.input.gitiles_commit.
  ///
  /// Setting this field will cause the created build to have a "buildset"
  /// tag with value "commit/gitiles/{hostname}/{project}/+/{id}".
  ///
  /// GitilesCommit objects MUST have host, project, ref fields set.
  final GitilesCommit? gitilesCommit;

  /// Tags to include in Build.tags of the created build.
  ///
  /// Note: tags of the created build may include other tags defined on the
  /// server.
  @TagsConverter()
  final Map<String?, List<String?>>? tags;

  /// Overrides default dimensions defined by builder config or template build.
  ///
  /// A set of entries with the same key defines a new or replaces an existing
  /// dimension with the same key.
  final List<RequestedDimension>? dimensions;

  // If not zero, overrides swarming task priority.
  // See also Build.infra.swarming.priority.
  final int? priority;

  /// The topic and user data to send build status updates to.
  final NotificationConfig? notify;

  /// The list fields to be included in the response.
  ///
  /// This is a comma separated list of Build proto fields to get included
  /// in the response.
  final String? fields;

  /// The CIPD package with the recipes.
  final Map<String, dynamic>? exe;

  @override
  Map<String, dynamic> toJson() => _$ScheduleBuildRequestToJson(this);

  @override
  String toString() {
    return 'scheduleBuildRequest(requestId: $requestId, builderId: $builderId, gitilesCommit: $gitilesCommit, fields: $fields, notify: $notify, exe: $exe)';
  }
}

/// A single build, identified by an int64 [id], belonging to a builder.
///
/// See also:
///   * [BuilderId]
///   * [GetBuildRequest]
@JsonSerializable(includeIfNull: false)
class Build extends JsonBody {
  /// Creates a build object.
  ///
  /// The [id] and [builderId] parameter is required.
  const Build({
    required this.id,
    required this.builderId,
    this.number,
    this.createdBy,
    this.canceledBy,
    this.startTime,
    this.endTime,
    this.status,
    this.tags,
    this.input,
    this.summaryMarkdown,
    this.critical,
  });

  /// Creates a [Build] object from JSON.
  static Build fromJson(Map<String, dynamic>? json) => _$BuildFromJson(json!);

  /// The BuildBucket ID for the build. Required.
  final String id;

  /// The [BuilderId] for the build.  Required.
  @JsonKey(name: 'builder')
  final BuilderId builderId;

  /// The LUCI build number for the build.
  ///
  /// This number corresponds to the order of builds, but build numbers may have
  /// gaps.
  final int? number;

  /// The verified LUCI identity that created the build.
  final String? createdBy;

  /// The verified LUCI identity that canceled the build.
  final String? canceledBy;

  /// The start time of the build.
  ///
  /// Required if and only if the [status] is [Status.started], [Status.success],
  /// or [Status.failure].
  final DateTime? startTime;

  /// The end time of the build.
  ///
  /// Required if and only if the [status] is terminal. Must not be before
  /// [startTime].
  final DateTime? endTime;

  /// The build status.
  ///
  /// Must be specified, and must not be [Status.unspecified].
  final Status? status;

  /// Human readable summary of the build in Markdown format.
  ///
  /// Up to 4kb.
  final String? summaryMarkdown;

  /// Arbitrary annotations for the build.
  ///
  /// The same key for a tag may be used multiple times.
  @TagsConverter()
  final Map<String?, List<String?>>? tags;

  /// If [Trinary.no], then the build status should not be used to assess the
  /// correctness of the input gitilesCommit or gerritChanges.
  final Trinary? critical;

  /// The build input values.
  final Input? input;

  @override
  Map<String, dynamic> toJson() => _$BuildToJson(this);

  @override
  String toString() => 'build(id: $id, builderId: $builderId, number: $number, status: $status, tags: $tags)';
}

/// A unique handle to a builder on BuildBucket.
@JsonSerializable(includeIfNull: false)
class BuilderId extends JsonBody {
  /// Creates a unique handle to a builder on BuildBucket.
  ///
  /// The bucket and builder control what ACLs for the infra, as specified in
  /// cr-buildbucket.cfg.
  const BuilderId({
    this.project,
    this.bucket,
    this.builder,
  });

  /// Creates a [BuilderId] object from JSON.
  static BuilderId fromJson(Map<String, dynamic> json) => _$BuilderIdFromJson(json);

  /// The project, e.g. "flutter", for the builder.
  final String? project;

  /// The bucket, e.g. "try" or "prod", for the builder.
  ///
  /// By convention, "prod" is for assets that will be released, "ci" is for
  /// reviewed code, and "try" is for untrusted code.
  final String? bucket;

  /// The builder from cr-buildbucket.cfg, e.g. "Linux" or "Linux Host Engine".
  final String? builder;

  @override
  Map<String, dynamic> toJson() => _$BuilderIdToJson(this);

  @override
  String toString() => '$project/$bucket/$builder';

  @override
  bool operator ==(Object other) =>
      other is BuilderId && other.bucket == bucket && other.builder == builder && other.project == project;

  @override
  int get hashCode => toString().hashCode;
}

/// Specifies a Cloud PubSub topic to send notification updates to from a
/// [ScheduleBuildRequest].
@JsonSerializable(includeIfNull: false)
class NotificationConfig extends JsonBody {
  const NotificationConfig({this.pubsubTopic, this.userData});

  static NotificationConfig fromJson(Map<String, dynamic> json) => _$NotificationConfigFromJson(json);

  /// The Cloud PubSub topic to use, e.g.
  /// `projects/flutter-dashboard/topics/luci-builds`.
  final String? pubsubTopic;

  /// An optional user data field that will be delivered with the message.
  ///
  /// May be omitted.
  @Base64Converter()
  final String? userData;

  @override
  Map<String, dynamic> toJson() => _$NotificationConfigToJson(this);

  @override
  String toString() => 'NotificationConfig(pubsubTopic: $pubsubTopic, userData: $userData)';
}

/// The build inputs for a build.
@JsonSerializable(includeIfNull: false)
class Input extends JsonBody {
  /// Creates a set of build inputs for a build.
  const Input({
    this.properties,
    this.gitilesCommit,
    this.experimental,
  });

  /// Creates an [Input] object from JSON.
  static Input fromJson(Map<String, dynamic> json) => _$InputFromJson(json);

  /// The build properties of a build.
  final Map<String, dynamic>? properties;

  /// The [GitilesCommit] information for a build.
  final GitilesCommit? gitilesCommit;

  /// Whether the build is experimental or not. Passed into the recipe as
  /// `api.runtime.is_experimental`.
  final bool? experimental;

  @override
  Map<String, dynamic> toJson() => _$InputToJson(this);
}

/// A landed Git commit hosted on Gitiles.
@JsonSerializable(includeIfNull: false)
class GitilesCommit extends JsonBody {
  /// Creates a object corresponding to a landed Git commit hosted on Gitiles.
  const GitilesCommit({
    this.host,
    this.project,
    this.ref,
    this.hash,
  });

  /// Creates a [GitilesCommit] object from JSON.
  static GitilesCommit fromJson(Map<String, dynamic> json) => _$GitilesCommitFromJson(json);

  /// The Gitiles host name, e.g. "chromium.googlesource.com"
  final String? host;

  /// The repository name on the host, e.g. "external/github.com/flutter/flutter".
  final String? project;

  /// The Git hash of the commit.
  @JsonKey(name: 'id')
  final String? hash;

  /// The Git ref of the commit, e.g. "refs/heads/master".
  final String? ref;

  @override
  Map<String, dynamic> toJson() => _$GitilesCommitToJson(this);
}

/// Build status values.
enum Status {
  /// Should not be used.
  @JsonValue('STATUS_UNSPECIFIED')
  unspecified,

  /// The status of a scheduled or pending build.
  @JsonValue('SCHEDULED')
  scheduled,

  /// The status of a started (running) build.
  @JsonValue('STARTED')
  started,

  /// A mask of `succes | failure | infraFailure | canceled`.
  @JsonValue('ENDED_MASK')
  ended,

  /// The build has successfully completed.
  @JsonValue('SUCCESS')
  success,

  /// The build has failed to complete some step due to a faulty test or commit.
  @JsonValue('FAILURE')
  failure,

  /// The build has failed due to an infrastructure related failure.
  @JsonValue('INFRA_FAILURE')
  infraFailure,

  /// The build was canceled.
  @JsonValue('CANCELED')
  canceled,
}

/// This type doesn't quite map to a bool, because there are actually four states
/// when you include whether it's present or not.
enum Trinary {
  /// A true value.
  @JsonValue('YES')
  yes,

  /// A false value.
  @JsonValue('NO')
  no,

  /// An explicit null value, which may or may not be treated differently from
  /// setting the JSON field to null.
  @JsonValue('UNSET')
  unset,
}

/// A requested dimension. Looks like StringPair, but also has an expiration.
@JsonSerializable(includeIfNull: false)
class RequestedDimension extends JsonBody {
  const RequestedDimension({
    required this.key,
    this.value,
    this.expiration,
  });

  static RequestedDimension fromJson(Map<String, dynamic> json) => _$RequestedDimensionFromJson(json);

  final String key;
  final String? value;

  /// If set, ignore this dimension after this duration. Must be a multiple of 1 minute. The format is '<seconds>s',
  /// e.g. '120s' represents 120 seconds.
  final String? expiration;

  @override
  Map<String, dynamic> toJson() => _$RequestedDimensionToJson(this);
}
