// Copyright 2017, the Flutter 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.

import 'dart:async';
import 'dart:ui' show hashValues;

import 'package:flutter/services.dart' show MethodChannel, PlatformException;
import 'package:meta/meta.dart' show visibleForTesting;

import 'src/common.dart';

export 'src/common.dart';
export 'widgets.dart';

enum SignInOption { standard, games }

class GoogleSignInAuthentication {
  GoogleSignInAuthentication._(this._data);

  final Map<String, dynamic> _data;

  /// An OpenID Connect ID token that identifies the user.
  String get idToken => _data['idToken'];

  /// The OAuth2 access token to access Google services.
  String get accessToken => _data['accessToken'];

  @override
  String toString() => 'GoogleSignInAuthentication:$_data';
}

class GoogleSignInAccount implements GoogleIdentity {
  GoogleSignInAccount._(this._googleSignIn, Map<String, dynamic> data)
      : displayName = data['displayName'],
        email = data['email'],
        id = data['id'],
        photoUrl = data['photoUrl'],
        _idToken = data['idToken'] {
    assert(id != null);
  }

  // These error codes must match with ones declared on Android and iOS sides.

  /// Error code indicating there was a failed attempt to recover user authentication.
  static const String kFailedToRecoverAuthError = 'failed_to_recover_auth';

  /// Error indicating that authentication can be recovered with user action;
  static const String kUserRecoverableAuthError = 'user_recoverable_auth';

  @override
  final String displayName;

  @override
  final String email;

  @override
  final String id;

  @override
  final String photoUrl;

  final String _idToken;
  final GoogleSignIn _googleSignIn;

  /// Retrieve [GoogleSignInAuthentication] for this account.
  ///
  /// [shouldRecoverAuth] sets whether to attempt to recover authentication if
  /// user action is needed. If an attempt to recover authentication fails a
  /// [PlatformException] is thrown with possible error code
  /// [kFailedToRecoverAuthError].
  ///
  /// Otherwise, if [shouldRecoverAuth] is false and the authentication can be
  /// recovered by user action a [PlatformException] is thrown with error code
  /// [kUserRecoverableAuthError].
  Future<GoogleSignInAuthentication> get authentication async {
    if (_googleSignIn.currentUser != this) {
      throw StateError('User is no longer signed in.');
    }

    final Map<String, dynamic> response =
        await GoogleSignIn.channel.invokeMapMethod<String, dynamic>(
      'getTokens',
      <String, dynamic>{
        'email': email,
        'shouldRecoverAuth': true,
      },
    );
    // On Android, there isn't an API for refreshing the idToken, so re-use
    // the one we obtained on login.
    if (response['idToken'] == null) {
      response['idToken'] = _idToken;
    }
    return GoogleSignInAuthentication._(response);
  }

  Future<Map<String, String>> get authHeaders async {
    final String token = (await authentication).accessToken;
    return <String, String>{
      "Authorization": "Bearer $token",
      "X-Goog-AuthUser": "0",
    };
  }

  /// Clears any client side cache that might be holding invalid tokens.
  ///
  /// If client runs into 401 errors using a token, it is expected to call
  /// this method and grab `authHeaders` once again.
  Future<void> clearAuthCache() async {
    final String token = (await authentication).accessToken;
    await GoogleSignIn.channel.invokeMethod<void>(
      'clearAuthCache',
      <String, dynamic>{'token': token},
    );
  }

  @override
  bool operator ==(dynamic other) {
    if (identical(this, other)) return true;
    if (other is! GoogleSignInAccount) return false;
    final GoogleSignInAccount otherAccount = other;
    return displayName == otherAccount.displayName &&
        email == otherAccount.email &&
        id == otherAccount.id &&
        photoUrl == otherAccount.photoUrl &&
        _idToken == otherAccount._idToken;
  }

  @override
  int get hashCode => hashValues(displayName, email, id, photoUrl, _idToken);

  @override
  String toString() {
    final Map<String, dynamic> data = <String, dynamic>{
      'displayName': displayName,
      'email': email,
      'id': id,
      'photoUrl': photoUrl,
    };
    return 'GoogleSignInAccount:$data';
  }
}

/// GoogleSignIn allows you to authenticate Google users.
class GoogleSignIn {
  /// Initializes global sign-in configuration settings.
  ///
  /// The [signInOption] determines the user experience. [SigninOption.games]
  /// must not be used on iOS.
  ///
  /// The list of [scopes] are OAuth scope codes to request when signing in.
  /// These scope codes will determine the level of data access that is granted
  /// to your application by the user. The full list of available scopes can
  /// be found here:
  /// <https://developers.google.com/identity/protocols/googlescopes>
  ///
  /// The [hostedDomain] argument specifies a hosted domain restriction. By
  /// setting this, sign in will be restricted to accounts of the user in the
  /// specified domain. By default, the list of accounts will not be restricted.
  GoogleSignIn({this.signInOption, this.scopes, this.hostedDomain});

  /// Factory for creating default sign in user experience.
  factory GoogleSignIn.standard({List<String> scopes, String hostedDomain}) {
    return GoogleSignIn(
        signInOption: SignInOption.standard,
        scopes: scopes,
        hostedDomain: hostedDomain);
  }

  /// Factory for creating sign in suitable for games. This option must not be
  /// used on iOS because the games API is not supported.
  factory GoogleSignIn.games() {
    return GoogleSignIn(signInOption: SignInOption.games);
  }

  // These error codes must match with ones declared on Android and iOS sides.

  /// Error code indicating there is no signed in user and interactive sign in
  /// flow is required.
  static const String kSignInRequiredError = 'sign_in_required';

  /// Error code indicating that interactive sign in process was canceled by the
  /// user.
  static const String kSignInCanceledError = 'sign_in_canceled';

  /// Error code indicating that attempt to sign in failed.
  static const String kSignInFailedError = 'sign_in_failed';

  /// The [MethodChannel] over which this class communicates.
  @visibleForTesting
  static const MethodChannel channel =
      MethodChannel('plugins.flutter.io/google_sign_in');

  /// Option to determine the sign in user experience. [SignInOption.games] must
  /// not be used on iOS.
  final SignInOption signInOption;

  /// The list of [scopes] are OAuth scope codes requested when signing in.
  final List<String> scopes;

  /// Domain to restrict sign-in to.
  final String hostedDomain;

  StreamController<GoogleSignInAccount> _currentUserController =
      StreamController<GoogleSignInAccount>.broadcast();

  /// Subscribe to this stream to be notified when the current user changes.
  Stream<GoogleSignInAccount> get onCurrentUserChanged =>
      _currentUserController.stream;

  // Future that completes when we've finished calling `init` on the native side
  Future<void> _initialization;

  Future<GoogleSignInAccount> _callMethod(String method) async {
    await _ensureInitialized();

    final Map<String, dynamic> response =
        await channel.invokeMapMethod<String, dynamic>(method);
    return _setCurrentUser(response != null && response.isNotEmpty
        ? GoogleSignInAccount._(this, response)
        : null);
  }

  GoogleSignInAccount _setCurrentUser(GoogleSignInAccount currentUser) {
    if (currentUser != _currentUser) {
      _currentUser = currentUser;
      _currentUserController.add(_currentUser);
    }
    return _currentUser;
  }

  Future<void> _ensureInitialized() {
    return _initialization ??=
        channel.invokeMethod<void>('init', <String, dynamic>{
      'signInOption': (signInOption ?? SignInOption.standard).toString(),
      'scopes': scopes ?? <String>[],
      'hostedDomain': hostedDomain,
    })
          ..catchError((dynamic _) {
            // Invalidate initialization if it errored out.
            _initialization = null;
          });
  }

  /// The most recently scheduled method call.
  Future<void> _lastMethodCall;

  /// Returns a [Future] that completes with a success after [future], whether
  /// it completed with a value or an error.
  static Future<void> _waitFor(Future<void> future) {
    final Completer<void> completer = Completer<void>();
    future.whenComplete(completer.complete).catchError((dynamic _) {
      // Ignore if previous call completed with an error.
    });
    return completer.future;
  }

  /// Adds call to [method] in a queue for execution.
  ///
  /// At most one in flight call is allowed to prevent concurrent (out of order)
  /// updates to [currentUser] and [onCurrentUserChanged].
  Future<GoogleSignInAccount> _addMethodCall(String method) async {
    Future<GoogleSignInAccount> response;
    if (_lastMethodCall == null) {
      response = _callMethod(method);
    } else {
      response = _lastMethodCall.then((_) {
        // If after the last completed call `currentUser` is not `null` and requested
        // method is a sign in method, re-use the same authenticated user
        // instead of making extra call to the native side.
        const List<String> kSignInMethods = <String>[
          'signIn',
          'signInSilently'
        ];
        if (kSignInMethods.contains(method) && _currentUser != null) {
          return _currentUser;
        } else {
          return _callMethod(method);
        }
      });
    }
    _lastMethodCall = _waitFor(response);
    return response;
  }

  /// The currently signed in account, or null if the user is signed out.
  GoogleSignInAccount get currentUser => _currentUser;
  GoogleSignInAccount _currentUser;

  /// Attempts to sign in a previously authenticated user without interaction.
  ///
  /// Returned Future resolves to an instance of [GoogleSignInAccount] for a
  /// successful sign in or `null` if there is no previously authenticated user.
  /// Use [signIn] method to trigger interactive sign in process.
  ///
  /// Authentication process is triggered only if there is no currently signed in
  /// user (that is when `currentUser == null`), otherwise this method returns
  /// a Future which resolves to the same user instance.
  ///
  /// Re-authentication can be triggered only after [signOut] or [disconnect].
  ///
  /// When [suppressErrors] is set to `false` and an error occurred during sign in
  /// returned Future completes with [PlatformException] whose `code` can be
  /// either [kSignInRequiredError] (when there is no authenticated user) or
  /// [kSignInFailedError] (when an unknown error occurred).
  Future<GoogleSignInAccount> signInSilently(
      {bool suppressErrors = true}) async {
    try {
      return await _addMethodCall('signInSilently');
    } catch (_) {
      if (suppressErrors) {
        return null;
      } else {
        rethrow;
      }
    }
  }

  /// Returns a future that resolves to whether a user is currently signed in.
  Future<bool> isSignedIn() async {
    await _ensureInitialized();
    return await channel.invokeMethod<bool>('isSignedIn');
  }

  /// Starts the interactive sign-in process.
  ///
  /// Returned Future resolves to an instance of [GoogleSignInAccount] for a
  /// successful sign in or `null` in case sign in process was aborted.
  ///
  /// Authentication process is triggered only if there is no currently signed in
  /// user (that is when `currentUser == null`), otherwise this method returns
  /// a Future which resolves to the same user instance.
  ///
  /// Re-authentication can be triggered only after [signOut] or [disconnect].
  Future<GoogleSignInAccount> signIn() {
    final Future<GoogleSignInAccount> result = _addMethodCall('signIn');
    bool isCanceled(dynamic error) =>
        error is PlatformException && error.code == kSignInCanceledError;
    return result.catchError((dynamic _) => null, test: isCanceled);
  }

  /// Marks current user as being in the signed out state.
  Future<GoogleSignInAccount> signOut() => _addMethodCall('signOut');

  /// Disconnects the current user from the app and revokes previous
  /// authentication.
  Future<GoogleSignInAccount> disconnect() => _addMethodCall('disconnect');
}
