// 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 'dart:async';

import 'package:meta/meta.dart';

import '../model/appengine/commit.dart';
import '../model/appengine/github_build_status_update.dart';
import '../model/appengine/stage.dart';
import '../model/appengine/task.dart';

import 'datastore.dart';

/// Function signature for a [BuildStatusService] provider.
typedef BuildStatusServiceProvider = BuildStatusService Function(
    DatastoreService datastoreService);

/// Class that calculates the current build status.
class BuildStatusService {
  const BuildStatusService(this.datastoreService)
      : assert(datastoreService != null);

  final DatastoreService datastoreService;

  /// Creates and returns a [DatastoreService] using [db] and [maxEntityGroups].
  static BuildStatusService defaultProvider(DatastoreService datastoreService) {
    return BuildStatusService(datastoreService);
  }

  @visibleForTesting
  static const int numberOfCommitsToReferenceForTreeStatus = 20;

  /// Calculates and returns the "overall" status of the Flutter build.
  ///
  /// This calculation operates by looking for the most recent success or
  /// failure for every (non-flaky) task in the manifest.
  ///
  /// Take the example build dashboard below:
  /// ✔ = passed, ✖ = failed, ☐ = new, ░ = in progress, s = skipped
  /// +---+---+---+---+
  /// | A | B | C | D |
  /// +---+---+---+---+
  /// | ✔ | ☐ | ░ | s |
  /// +---+---+---+---+
  /// | ✔ | ░ | ✔ | ✖ |
  /// +---+---+---+---+
  /// | ✔ | ✖ | ✔ | ✔ |
  /// +---+---+---+---+
  /// This build will fail because only of Task B. Task D is not included in
  /// the latest commit status, so it does not impact the build status.
  /// Task B fails because its last known status was to be failing, even though
  /// there is currently a newer version that is in progress.
  Future<BuildStatus> calculateCumulativeStatus({String branch}) async {
    final List<CommitStatus> statuses = await retrieveCommitStatus(
      limit: numberOfCommitsToReferenceForTreeStatus,
      branch: branch,
    ).toList();
    if (statuses.isEmpty) {
      return BuildStatus.failed;
    }

    final Map<String, bool> tasksInProgress =
        _findTasksRelevantToLatestStatus(statuses);
    if (tasksInProgress.isEmpty) {
      return BuildStatus.failed;
    }

    for (CommitStatus status in statuses) {
      for (Stage stage in status.stages) {
        for (Task task in stage.tasks) {
          /// If a task [isRelevantToLatestStatus] but has not run yet, we look
          /// for a previous run of the task from the previous commit.
          final bool isRelevantToLatestStatus =
              tasksInProgress.containsKey(task.name);

          /// Tasks that are not relevant to the latest status will have a
          /// null value in the map.
          final bool taskInProgress = tasksInProgress[task.name] ?? true;

          if (isRelevantToLatestStatus && taskInProgress) {
            if (task.isFlaky || _isSuccessful(task)) {
              /// This task no longer needs to be checked to see if it causing
              /// the build status to fail.
              tasksInProgress[task.name] = false;
            } else if (_isFailed(task) || _isRerunning(task)) {
              return BuildStatus.failed;
            }
          }
        }
      }
    }

    return BuildStatus.succeeded;
  }

  /// Creates a map of the tasks that need to be checked for the build status.
  ///
  /// This is based on the most recent [CommitStatus] and all of its tasks.
  Map<String, bool> _findTasksRelevantToLatestStatus(
      List<CommitStatus> statuses) {
    final Map<String, bool> tasks = <String, bool>{};

    for (Stage stage in statuses.first.stages) {
      for (Task task in stage.tasks) {
        tasks[task.name] = true;
      }
    }

    return tasks;
  }

  /// Retrieves the comprehensive status of every task that runs per commit.
  ///
  /// The returned stream will be ordered by most recent commit first, then
  /// the next newest, and so on.
  Stream<CommitStatus> retrieveCommitStatus(
      {int limit, int timestamp, String branch}) async* {
    await for (Commit commit in datastoreService.queryRecentCommits(
        limit: limit, timestamp: timestamp, branch: branch)) {
      final List<Stage> stages =
          await datastoreService.queryTasksGroupedByStage(commit);
      yield CommitStatus(commit, stages);
    }
  }

  bool _isFailed(Task task) {
    return task.status == Task.statusFailed;
  }

  bool _isSuccessful(Task task) {
    return task.status == Task.statusSucceeded;
  }

  bool _isRerunning(Task task) {
    return task.attempts > 1 &&
        (task.status == Task.statusInProgress || task.status == Task.statusNew);
  }
}

/// Class that holds the status for all tasks corresponding to a particular
/// commit.
///
/// Tasks may still be running, and thus their status is subject to change.
/// Put another way, this class holds information that is a snapshot in time.
@immutable
class CommitStatus {
  /// Creates a new [CommitStatus].
  const CommitStatus(this.commit, this.stages);

  /// The commit against which all the tasks in [stages] are run.
  final Commit commit;

  /// The partitioned stages, each of which holds a bucket of tasks that
  /// belong in the stage.
  final List<Stage> stages;
}

@immutable
class BuildStatus {
  const BuildStatus._(this.value);

  final String value;

  static const BuildStatus succeeded =
      BuildStatus._(GithubBuildStatusUpdate.statusSuccess);
  static const BuildStatus failed =
      BuildStatus._(GithubBuildStatusUpdate.statusFailure);

  String get githubStatus => value;

  @override
  String toString() => value;
}
