// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library oauth2_client;

import 'dart:async';
import 'dart:uri';

import 'package:http/http.dart' as http;

import 'authorization_exception.dart';
import 'credentials.dart';
import 'expiration_exception.dart';
import 'utils.dart';

// TODO(nweiz): Add an onCredentialsRefreshed event once we have some event
// infrastructure.
/// An OAuth2 client. This acts as a drop-in replacement for an [http.Client],
/// while sending OAuth2 authorization credentials along with each request.
///
/// The client also automatically refreshes its credentials if possible. When it
/// makes a request, if its credentials are expired, it will first refresh them.
/// This means that any request may throw an [AuthorizationException] if the
/// refresh is not authorized for some reason, a [FormatException] if the
/// authorization server provides ill-formatted responses, or an
/// [ExpirationException] if the credentials are expired and can't be refreshed.
///
/// The client will also throw an [AuthorizationException] if the resource
/// server returns a 401 response with a WWW-Authenticate header indicating that
/// the current credentials are invalid.
///
/// If you already have a set of [Credentials], you can construct a [Client]
/// directly. However, in order to first obtain the credentials, you must
/// authorize. At the time of writing, the only authorization method this
/// library supports is [AuthorizationCodeGrant].
class Client extends http.BaseClient {
  /// The client identifier for this client. The authorization server will issue
  /// each client a separate client identifier and secret, which allows the
  /// server to tell which client is accessing it. Some servers may also have an
  /// anonymous identifier/secret pair that any client may use.
  ///
  /// This is usually global to the program using this library.
  final String identifier;

  /// The client secret for this client. The authorization server will issue
  /// each client a separate client identifier and secret, which allows the
  /// server to tell which client is accessing it. Some servers may also have an
  /// anonymous identifier/secret pair that any client may use.
  ///
  /// This is usually global to the program using this library.
  ///
  /// Note that clients whose source code or binary executable is readily
  /// available may not be able to make sure the client secret is kept a secret.
  /// This is fine; OAuth2 servers generally won't rely on knowing with
  /// certainty that a client is who it claims to be.
  final String secret;

  /// The credentials this client uses to prove to the resource server that it's
  /// authorized. This may change from request to request as the credentials
  /// expire and the client refreshes them automatically.
  Credentials get credentials => _credentials;
  Credentials _credentials;

  /// The underlying HTTP client.
  http.Client _httpClient;

  /// Creates a new client from a pre-existing set of credentials. When
  /// authorizing a client for the first time, you should use
  /// [AuthorizationCodeGrant] instead of constructing a [Client] directly.
  ///
  /// [httpClient] is the underlying client that this forwards requests to after
  /// adding authorization credentials to them.
  Client(
      this.identifier,
      this.secret,
      this._credentials,
      {http.Client httpClient})
    : _httpClient = httpClient == null ? new http.Client() : httpClient;

  /// Sends an HTTP request with OAuth2 authorization credentials attached. This
  /// will also automatically refresh this client's [Credentials] before sending
  /// the request if necessary.
  Future<http.StreamedResponse> send(http.BaseRequest request) {
    return async.then((_) {
      if (!credentials.isExpired) return new Future.value();
      if (!credentials.canRefresh) throw new ExpirationException(credentials);
      return refreshCredentials();
    }).then((_) {
      request.headers['authorization'] = "Bearer ${credentials.accessToken}";
      return _httpClient.send(request);
    }).then((response) {
      if (response.statusCode != 401 ||
          !response.headers.containsKey('www-authenticate')) {
        return response;
      }

      var authenticate;
      try {
        authenticate = new AuthenticateHeader.parse(
            response.headers['www-authenticate']);
      } on FormatException catch (e) {
        return response;
      }

      if (authenticate.scheme != 'bearer') return response;

      var params = authenticate.parameters;
      if (!params.containsKey('error')) return response;

      throw new AuthorizationException(
          params['error'], params['error_description'],
          Uri.parse(params['error_uri']));
    });
  }

  /// Explicitly refreshes this client's credentials. Returns this client.
  ///
  /// This will throw a [StateError] if the [Credentials] can't be refreshed, an
  /// [AuthorizationException] if refreshing the credentials fails, or a
  /// [FormatError] if the authorization server returns invalid responses.
  ///
  /// You may request different scopes than the default by passing in
  /// [newScopes]. These must be a subset of the scopes in the
  /// [Credentials.scopes] field of [Client.credentials].
  Future<Client> refreshCredentials([List<String> newScopes]) {
    return async.then((_) {
      if (!credentials.canRefresh) {
        var prefix = "OAuth credentials";
        if (credentials.isExpired) prefix = "$prefix have expired and";
        throw new StateError("$prefix can't be refreshed.");
      }

      return credentials.refresh(identifier, secret,
          newScopes: newScopes, httpClient: _httpClient);
    }).then((credentials) {
      _credentials = credentials;
      return this;
    });
  }

  /// Closes this client and its underlying HTTP client.
  void close() {
    if (_httpClient != null) _httpClient.close();
    _httpClient = null;
  }
}
