// 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:convert';
import 'dart:io';

import 'package:googleapis_auth/auth_io.dart';
import 'package:meta/meta.dart';

import '../model/luci/buildbucket.dart';
import '../request_handling/body.dart';
import 'access_token_provider.dart';

/// A client interface to LUCI BuildBucket
@immutable
class BuildBucketClient {
  /// Creates a new build bucket Client.
  ///
  /// The [buildBucketUri] parameter must not be null, and will be defaulted to
  /// [kDefaultBuildBucketUri] if not specified.
  ///
  /// The [httpClient] parameter will be defaulted to `HttpClient()` if not
  /// specified or null.
  BuildBucketClient({
    this.buildBucketUri = kDefaultBuildBucketUri,
    this.accessTokenService,
    HttpClient httpClient,
  })  : assert(buildBucketUri != null),
        httpClient = httpClient ?? HttpClient();

  /// Garbage to prevent browser/JSON parsing exploits.
  static const String kRpcResponseGarbage = ")]}'";

  /// The default endpoint for BuildBucket requests.
  static const String kDefaultBuildBucketUri =
      'https://cr-buildbucket.appspot.com/prpc/buildbucket.v2.Builds';

  /// The base URI for build bucket requests.
  ///
  /// Defaults to [kDefaultBuildBucketUri].
  final String buildBucketUri;

  /// The token provider for OAuth2 requests.
  ///
  /// If this is non-null, an access token will be attached to any outbound
  /// HTTP requests issued by this client.
  final AccessTokenService accessTokenService;

  /// The [HttpClient] to use for requests.
  ///
  /// Defaults to `HttpClient()`.
  final HttpClient httpClient;

  Future<T> _postRequest<S extends JsonBody, T>(
    String path,
    S request,
    T responseFromJson(Map<String, dynamic> rawResponse),
  ) async {
    final Uri url = Uri.parse('$buildBucketUri$path');
    final HttpClientRequest httpRequest = await httpClient.postUrl(url);

    httpRequest.headers.add(HttpHeaders.contentTypeHeader, 'application/json');
    httpRequest.headers.add(HttpHeaders.acceptHeader, 'application/json');

    if (accessTokenService != null) {
      final AccessToken token = await accessTokenService.createAccessToken(
        scopes: <String>[
          'openid',
          'https://www.googleapis.com/auth/userinfo.profile',
          'https://www.googleapis.com/auth/userinfo.email',
        ],
      );
      if (token != null) {
        httpRequest.headers.add(
            HttpHeaders.authorizationHeader, '${token.type} ${token.data}');
      }
    }

    httpRequest.write(json.encode(request.toJson()));
    await httpRequest.flush();
    final HttpClientResponse response = await httpRequest.close();

    final String rawResponse = await utf8.decodeStream(response);
    if (response.statusCode < 300) {
      return responseFromJson(
          json.decode(rawResponse.substring(kRpcResponseGarbage.length))
              as Map<String, dynamic>);
    }
    throw BuildBucketException(response.statusCode, rawResponse);
  }

  /// The RPC request to schedule a build.
  Future<Build> scheduleBuild(ScheduleBuildRequest request) {
    return _postRequest<ScheduleBuildRequest, Build>(
      '/ScheduleBuild',
      request,
      Build.fromJson,
    );
  }

  /// The RPC request to search for builds.
  Future<SearchBuildsResponse> searchBuilds(SearchBuildsRequest request) {
    return _postRequest<SearchBuildsRequest, SearchBuildsResponse>(
      '/SearchBuilds',
      request,
      SearchBuildsResponse.fromJson,
    );
  }

  /// The RPC method to batch multiple RPC methods in a single HTTP request.
  ///
  /// The response is guaranteed to contain line-item responses for all
  /// line-item requests that were issued in [request]. If only a subset of
  /// responses were retrieved, a [BatchRequestException] will be thrown.
  Future<BatchResponse> batch(BatchRequest request) async {
    final BatchResponse response =
        await _postRequest<BatchRequest, BatchResponse>(
      '/Batch',
      request,
      BatchResponse.fromJson,
    );
    if (response.responses.length != request.requests.length) {
      throw BatchRequestException('Failed to execute all requests');
    }
    return response;
  }

  /// The RPC request to cancel a build.
  Future<Build> cancelBuild(CancelBuildRequest request) {
    return _postRequest<CancelBuildRequest, Build>(
      '/CancelBuild',
      request,
      Build.fromJson,
    );
  }

  /// The RPC request to get details about a build.
  Future<Build> getBuild(GetBuildRequest request) {
    return _postRequest<GetBuildRequest, Build>(
      '/GetBuild',
      request,
      Build.fromJson,
    );
  }

  /// Closes the underlying [HttpClient].
  ///
  /// If `force` is true, it will close immediately and cause outstanding
  /// requests to end with an error. Otherwise, it will wait for outstanding
  /// requests to finish before closing.
  ///
  /// Once this call completes, additional RPC requests will throw an exception.
  void close({bool force = false}) {
    httpClient.close(force: force);
  }
}

class BuildBucketException implements Exception {
  const BuildBucketException(this.statusCode, this.message);

  /// The HTTP status code of the error.
  final int statusCode;

  /// The message from the server.
  final String message;

  @override
  String toString() => '$runtimeType: [$statusCode]: $message';
}

class BatchRequestException implements Exception {
  BatchRequestException(this.message);

  final String message;

  @override
  String toString() => message;
}
