// 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 credentials_test;

import 'dart:async';
import 'dart:io';
import 'dart:json' as JSON;
import 'dart:uri';

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

import 'utils.dart';

final Uri tokenEndpoint = Uri.parse('http://example.com/token');

ExpectClient httpClient;

void main() {
  setUp(() => httpClient = new ExpectClient());

  test('is not expired if no expiration exists', () {
    var credentials = new oauth2.Credentials('access token');
    expect(credentials.isExpired, isFalse);
  });

  test('is not expired if the expiration is in the future', () {
    var expiration = new DateTime.now().add(new Duration(hours: 1));
    var credentials = new oauth2.Credentials(
        'access token', null, null, null, expiration);
    expect(credentials.isExpired, isFalse);
  });

  test('is expired if the expiration is in the past', () {
    var expiration = new DateTime.now().subtract(new Duration(hours: 1));
    var credentials = new oauth2.Credentials(
        'access token', null, null, null, expiration);
    expect(credentials.isExpired, isTrue);
  });

  test("can't refresh without a refresh token", () {
    var credentials = new oauth2.Credentials(
        'access token', null, tokenEndpoint);
    expect(credentials.canRefresh, false);
    credentials.refresh('identifier', 'secret', httpClient: httpClient)
        .catchError(expectAsync1((error) {
          expect(error is StateError, isTrue);
        }));
  });

  test("can't refresh without a token endpoint", () {
    var credentials = new oauth2.Credentials('access token', 'refresh token');
    expect(credentials.canRefresh, false);
    credentials.refresh('identifier', 'secret', httpClient: httpClient)
        .catchError(expectAsync1((error) {
          expect(error is StateError, isTrue);
        }));
  });

  test("can refresh with a refresh token and a token endpoint", () {
    var credentials = new oauth2.Credentials(
        'access token', 'refresh token', tokenEndpoint, ['scope1', 'scope2']);
    expect(credentials.canRefresh, true);

    httpClient.expectRequest((request) {
      expect(request.method, equals('POST'));
      expect(request.url.toString(), equals(tokenEndpoint.toString()));
      expect(request.bodyFields, equals({
        "grant_type": "refresh_token",
        "refresh_token": "refresh token",
        "scope": "scope1 scope2",
        "client_id": "identifier",
        "client_secret": "secret"
      }));

      return new Future.value(new http.Response(JSON.stringify({
        'access_token': 'new access token',
        'token_type': 'bearer',
        'refresh_token': 'new refresh token'
      }), 200, headers: {'content-type': 'application/json'}));
    });

    
    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient)
        .then((credentials) {
      expect(credentials.accessToken, equals('new access token'));
      expect(credentials.refreshToken, equals('new refresh token'));
    }), completes);
  });

  test("uses the old refresh token if a new one isn't provided", () {
    var credentials = new oauth2.Credentials(
        'access token', 'refresh token', tokenEndpoint);
    expect(credentials.canRefresh, true);

    httpClient.expectRequest((request) {
      expect(request.method, equals('POST'));
      expect(request.url.toString(), equals(tokenEndpoint.toString()));
      expect(request.bodyFields, equals({
        "grant_type": "refresh_token",
        "refresh_token": "refresh token",
        "client_id": "identifier",
        "client_secret": "secret"
      }));

      return new Future.value(new http.Response(JSON.stringify({
        'access_token': 'new access token',
        'token_type': 'bearer'
      }), 200, headers: {'content-type': 'application/json'}));
    });

    
    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient)
        .then((credentials) {
      expect(credentials.accessToken, equals('new access token'));
      expect(credentials.refreshToken, equals('refresh token'));
    }), completes);
  });

  group("fromJson", () {
    oauth2.Credentials fromMap(Map map) =>
      new oauth2.Credentials.fromJson(JSON.stringify(map));

    test("should load the same credentials from toJson", () {
      var expiration = new DateTime.now().subtract(new Duration(hours: 1));
      var credentials = new oauth2.Credentials(
          'access token', 'refresh token', tokenEndpoint, ['scope1', 'scope2'],
          expiration);
      var reloaded = new oauth2.Credentials.fromJson(credentials.toJson());

      expect(reloaded.accessToken, equals(credentials.accessToken));
      expect(reloaded.refreshToken, equals(credentials.refreshToken));
      expect(reloaded.tokenEndpoint.toString(),
          equals(credentials.tokenEndpoint.toString()));
      expect(reloaded.scopes, equals(credentials.scopes));
      expect(reloaded.expiration, equals(credentials.expiration));
    });

    test("should throw a FormatException for invalid JSON", () {
      expect(() => new oauth2.Credentials.fromJson("foo bar"),
          throwsFormatException);
    });

    test("should throw a FormatException for JSON that's not a map", () {
      expect(() => new oauth2.Credentials.fromJson("null"),
          throwsFormatException);
    });

    test("should throw a FormatException if there is no accessToken", () {
      expect(() => fromMap({}), throwsFormatException);
    });

    test("should throw a FormatException if accessToken is not a string", () {
      expect(() => fromMap({"accessToken": 12}), throwsFormatException);
    });

    test("should throw a FormatException if refreshToken is not a string", () {
      expect(() => fromMap({"accessToken": "foo", "refreshToken": 12}),
          throwsFormatException);
    });

    test("should throw a FormatException if tokenEndpoint is not a string", () {
      expect(() => fromMap({"accessToken": "foo", "tokenEndpoint": 12}),
          throwsFormatException);
    });

    test("should throw a FormatException if scopes is not a list", () {
      expect(() => fromMap({"accessToken": "foo", "scopes": 12}),
          throwsFormatException);
    });

    test("should throw a FormatException if expiration is not an int", () {
      expect(() => fromMap({"accessToken": "foo", "expiration": "12"}),
          throwsFormatException);
    });
  });
}
