// 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 'package:meta/meta.dart';

import 'commit.dart';
import 'task.dart';

part 'stage.g.dart';

/// A group of related [Task]s run against a particular [Commit].
///
/// Stages are grouped by the infrastructure family that runs them, such as
/// Cirrus, LUCI, DeviceLab on Linux, DeviceLab on Windows, etc.
@immutable
@JsonSerializable(createFactory: false, ignoreUnannotated: true)
class Stage implements Comparable<Stage> {
  const Stage(this.name, this.commit, this.tasks, this.taskStatus);

  const Stage._(this.name, this.commit, this.tasks, this.taskStatus);

  /// The fixed ordering of the stages (by name).
  ///
  /// Unknown stages will be placed at the end of any ordering.
  static const List<String?> _order = <String?>[
    'cirrus',
    'chromebot',
    'devicelab',
    'devicelab_win',
    'devicelab_ios',
  ];

  /// Arbitrarily large index to represent the "end of the ordering".
  static const int _endOfList = 1000000;

  /// The name of the stage (e.g. 'cirrus', 'devicelab', 'devicelab_win').
  ///
  /// This is guaranteed to be non-null.
  @JsonKey(name: 'Name')
  final String? name;

  /// The commit that owns this stage.
  ///
  /// All [tasks] will be run against this commit.
  final Commit? commit;

  /// The list of tasks in this stage.
  ///
  /// These tasks will be run against [commit]. This list is guaranteed to be
  /// non-empty.
  final List<Task> tasks;

  /// Representation of [tasks] used for JSON serialization.
  @JsonKey(name: 'Tasks')
  List<SerializableTask> get serializableTasks {
    return tasks.map<SerializableTask>((Task task) => SerializableTask(task)).toList();
  }

  /// The aggregate status, accounting for all [tasks] in this stage.
  ///
  /// The status is defined as follows:
  ///
  ///  * If all tasks in this stage succeeded, then [Task.statusSucceeded]
  ///  * If at least one task in this stage failed, then [Task.statusFailed]
  ///  * If all tasks have the same status, then that status
  ///  * Else [Task.statusInProgress]
  @JsonKey(name: 'Status')
  final String taskStatus;

  /// Whether this stage is managed by the Flutter device lab.
  ///
  /// Stages such as 'cirrus' and 'chromebot' are not managed by the Flutter
  /// device lab.
  bool get isManagedByDeviceLab => name!.startsWith('devicelab');

  @override
  int compareTo(Stage other) => _orderIndex(this).compareTo(_orderIndex(other));

  static int _orderIndex(Stage stage) {
    int index = _order.indexOf(stage.name);
    if (index == -1) {
      // Put unknown stages last.
      index = _endOfList;
    }
    return index;
  }

  /// Serializes this object to a JSON primitive.
  Map<String, dynamic> toJson() => _$StageToJson(this);

  @override
  String toString() {
    final StringBuffer buf = StringBuffer()
      ..write('$runtimeType(')
      ..write('name: $name')
      ..write(', commit: ${commit?.sha}')
      ..write(', tasks: ${tasks.length}')
      ..write(', taskStatus: $taskStatus')
      ..write(')');
    return buf.toString();
  }
}

/// A mutable class used to build instances of [Stage].
class StageBuilder {
  /// The name of the stage.
  ///
  /// See also:
  ///  * [Stage.name]
  String? name;

  /// The commit that owns the stage.
  ///
  /// See also:
  ///  * [Stage.commit]
  Commit? commit;

  /// The tasks within the stage, run against [commit].
  ///
  /// See also:
  ///  * [Stage.commit]
  List<Task> tasks = <Task>[];

  /// Builds a [Stage] from the information in this builder.
  ///
  /// Throws a [StateError] if [name] is null, [commit] is null, or [tasks] is
  /// empty.
  Stage build() {
    if (name == null) {
      throw StateError('Cannot build a stage with no name');
    }
    if (commit == null) {
      throw StateError('Cannot build a stage with no commit ($name)');
    }
    if (tasks.isEmpty) {
      throw StateError('Cannot build a stage with no tasks ($name)');
    }
    return Stage._(name, commit, List<Task>.unmodifiable(tasks), _taskStatus);
  }

  String get _taskStatus {
    assert(tasks.isNotEmpty);
    bool isSucceeded(Task task) => task.status == Task.statusSucceeded;
    bool isFailed(Task task) => task.status == Task.statusFailed;

    if (tasks.every(isSucceeded)) {
      return Task.statusSucceeded;
    }

    if (tasks.any(isFailed)) {
      return Task.statusFailed;
    }

    final String? commonStatus =
        tasks.map<String?>((Task task) => task.status).reduce((String? a, String? b) => a == b ? a : null);
    return commonStatus ?? Task.statusInProgress;
  }
}
