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

import '../datastore/cocoon_config.dart';
import '../model/appengine/task.dart';
import '../model/luci/buildbucket.dart';
import '../request_handling/api_request_handler.dart';

import 'buildbucket.dart';

part 'luci.g.dart';

const int _maxResults = 40;
const Map<Status, String> _luciStatusToTaskStatus = <Status, String>{
  Status.unspecified: Task.statusInProgress,
  Status.scheduled: Task.statusInProgress,
  Status.started: Task.statusInProgress,
  Status.canceled: Task.statusSkipped,
  Status.success: Task.statusSucceeded,
  Status.failure: Task.statusFailed,
  Status.infraFailure: Task.statusFailed,
};

typedef LuciServiceProvider = LuciService Function(
    ApiRequestHandler<dynamic> handler);

/// Service class for interacting with LUCI.
@immutable
class LuciService {
  /// Creates a new [LuciService].
  ///
  /// The [config] and [clientContext] arguments must not be null.
  const LuciService({
    @required this.config,
    @required this.clientContext,
  })  : assert(config != null),
        assert(clientContext != null);

  /// The Cocoon configuration. Guaranteed to be non-null.
  final Config config;

  /// The AppEngine context to use for requests. Guaranteed to be non-null.
  final ClientContext clientContext;

  /// Gets the list of recent LUCI tasks, broken out by the [BranchLuciBuilder]
  ///  that owns them.
  ///
  /// The list of known LUCI builders is specified in [LuciBuilder.all].
  Future<Map<BranchLuciBuilder, Map<String, List<LuciTask>>>>
      getBranchRecentTasks({
    String repo,
    bool requireTaskName = false,
  }) async {
    assert(requireTaskName != null);
    final List<LuciBuilder> builders = await LuciBuilder.getBuilders(config);
    final Iterable<Build> builds =
        await getBuilds(repo, requireTaskName, builders);

    final Map<BranchLuciBuilder, Map<String, List<LuciTask>>> results =
        <BranchLuciBuilder, Map<String, List<LuciTask>>>{};
    for (Build build in builds) {
      final String commit = build.input?.gitilesCommit?.hash ?? 'unknown';
      final String ref = build.input?.gitilesCommit?.ref ?? 'unknown';
      final LuciBuilder builder = builders.singleWhere((LuciBuilder builder) {
        return builder.name == build.builderId.builder;
      });
      final BranchLuciBuilder branchLuciBuilder =
          BranchLuciBuilder(luciBuilder: builder, branch: ref.split('/')[2]);
      results[branchLuciBuilder] ??= <String, List<LuciTask>>{};
      results[branchLuciBuilder][commit] ??= <LuciTask>[];
      results[branchLuciBuilder][commit].add(LuciTask(
        commitSha: commit,
        ref: ref,
        status: _luciStatusToTaskStatus[build.status],
        buildNumber: build.number,
      ));
    }
    return results;
  }

  /// Gets the list of recent LUCI tasks, broken out by the [LuciBuilder] that
  /// owns them.
  ///
  /// The list of known LUCI builders is specified in [LuciBuilder.all].
  Future<Map<LuciBuilder, List<LuciTask>>> getRecentTasks({
    String repo,
    bool requireTaskName = false,
  }) async {
    assert(requireTaskName != null);
    final List<LuciBuilder> builders = await LuciBuilder.getBuilders(config);
    final Iterable<Build> builds =
        await getBuilds(repo, requireTaskName, builders);

    final Map<LuciBuilder, List<LuciTask>> results =
        <LuciBuilder, List<LuciTask>>{};
    for (Build build in builds) {
      final String commit = build.input?.gitilesCommit?.hash ?? 'unknown';
      final String ref = build.input?.gitilesCommit?.ref ?? 'unknown';
      final LuciBuilder builder = builders.singleWhere((LuciBuilder builder) {
        return builder.name == build.builderId.builder;
      });
      results[builder] ??= <LuciTask>[];
      results[builder].add(LuciTask(
        commitSha: commit,
        ref: ref,
        status: _luciStatusToTaskStatus[build.status],
        buildNumber: build.number,
      ));
    }
    return results;
  }

  /// Gets list of [build] for [repo] and available Luci [builders]
  /// predefined in cocoon config.
  ///
  /// Latest builds of each builder will be returned from new to old.
  Future<Iterable<Build>> getBuilds(
      String repo, bool requireTaskName, List<LuciBuilder> builders) async {
    final BuildBucketClient buildBucketClient = BuildBucketClient();

    bool includeBuilder(LuciBuilder builder) {
      if (repo != null && builder.repo != repo) {
        return false;
      }
      if (requireTaskName && builder.taskName == null) {
        return false;
      }
      return true;
    }

    final List<Request> searchRequests =
        builders.where(includeBuilder).map<Request>((LuciBuilder builder) {
      return Request(
        searchBuilds: SearchBuildsRequest(
          pageSize: _maxResults,
          predicate: BuildPredicate(
            builderId: BuilderId(
              project: 'flutter',
              bucket: 'prod',
              builder: builder.name,
            ),
          ),
        ),
      );
    }).toList();
    final BatchRequest batchRequest = BatchRequest(requests: searchRequests);
    final BatchResponse batchResponse =
        await buildBucketClient.batch(batchRequest);
    final Iterable<Build> builds = batchResponse.responses
        .map<SearchBuildsResponse>((Response response) => response.searchBuilds)
        .expand<Build>((SearchBuildsResponse response) => response.builds);
    return builds;
  }
}

@immutable
class BranchLuciBuilder {
  const BranchLuciBuilder({
    this.luciBuilder,
    this.branch,
  });

  final String branch;
  final LuciBuilder luciBuilder;
}

@immutable
@JsonSerializable()
class LuciBuilder {
  const LuciBuilder({
    @required this.name,
    @required this.repo,
    this.taskName,
  }) : assert(name != null);

  /// Create a new [LuciBuilder] object from its JSON representation.
  factory LuciBuilder.fromJson(Map<String, dynamic> json) =>
      _$LuciBuilderFromJson(json);

  /// The name of this builder.
  @JsonKey(required: true, disallowNullValue: true)
  final String name;

  /// The name of the repository for which this builder runs.
  @JsonKey(required: true, disallowNullValue: true)
  final String repo;

  /// The name of the devicelab task associated with this builder.
  @JsonKey()
  final String taskName;

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

  /// Loads and returns the list of known builders from the Cocoon [config].
  static Future<List<LuciBuilder>> getBuilders(Config config) async {
    final List<dynamic> builders = config.luciBuilders;
    return builders
        .map<LuciBuilder>((dynamic json) =>
            LuciBuilder.fromJson(json as Map<String, dynamic>))
        .toList();
  }
}

@immutable
class LuciTask {
  const LuciTask({
    @required this.commitSha,
    @required this.ref,
    @required this.status,
    @required this.buildNumber,
  })  : assert(commitSha != null),
        assert(ref != null),
        assert(status != null),
        assert(buildNumber != null);

  /// The GitHub commit at which this task is being run.
  final String commitSha;

  // The GitHub ref at which this task is being run.
  final String ref;

  /// The status of this task. See the [Task] class for supported values.
  final String status;

  /// The build number of this task.
  final int buildNumber;
}
