// 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
/// 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?>[
    '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. '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 '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;
  }
}
