// Copyright 2013 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:flutter/foundation.dart' show visibleForTesting;

import 'src/method_channel_google_sign_in.dart';
import 'src/types.dart';

export 'src/method_channel_google_sign_in.dart';
export 'src/types.dart';

/// The interface that implementations of google_sign_in must implement.
///
/// Platform implementations that live in a separate package should extend this
/// class rather than implement it as `google_sign_in` does not consider newly
/// added methods to be breaking changes. Extending this class (using `extends`)
/// ensures that the subclass will get the default implementation, while
/// platform implementations that `implements` this interface will be broken by
/// newly added [GoogleSignInPlatform] methods.
abstract class GoogleSignInPlatform {
  /// Only mock implementations should set this to `true`.
  ///
  /// Mockito mocks implement this class with `implements` which is forbidden
  /// (see class docs). This property provides a backdoor for mocks to skip the
  /// verification that the class isn't implemented with `implements`.
  @visibleForTesting
  bool get isMock => false;

  /// The default instance of [GoogleSignInPlatform] to use.
  ///
  /// Platform-specific plugins should override this with their own
  /// platform-specific class that extends [GoogleSignInPlatform] when they
  /// register themselves.
  ///
  /// Defaults to [MethodChannelGoogleSignIn].
  static GoogleSignInPlatform get instance => _instance;

  static GoogleSignInPlatform _instance = MethodChannelGoogleSignIn();

  // TODO(amirh): Extract common platform interface logic.
  // https://github.com/flutter/flutter/issues/43368
  static set instance(GoogleSignInPlatform instance) {
    if (!instance.isMock) {
      try {
        instance._verifyProvidesDefaultImplementations();
      } on NoSuchMethodError catch (_) {
        throw AssertionError(
            'Platform interfaces must not be implemented with `implements`');
      }
    }
    _instance = instance;
  }

  /// This method ensures that [GoogleSignInPlatform] isn't implemented with `implements`.
  ///
  /// See class docs for more details on why using `implements` to implement
  /// [GoogleSignInPlatform] is forbidden.
  ///
  /// This private method is called by the [instance] setter, which should fail
  /// if the provided instance is a class implemented with `implements`.
  void _verifyProvidesDefaultImplementations() {}

  /// Initializes the plugin. Deprecated: call [initWithParams] instead.
  ///
  /// 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.
  ///
  /// 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 [signInOption] determines the user experience. [SigninOption.games] is
  /// only supported on Android.
  ///
  /// See:
  /// https://developers.google.com/identity/sign-in/web/reference#gapiauth2initparams
  Future<void> init({
    List<String> scopes = const <String>[],
    SignInOption signInOption = SignInOption.standard,
    String? hostedDomain,
    String? clientId,
  }) async {
    throw UnimplementedError('init() has not been implemented.');
  }

  /// Initializes the plugin with specified [params]. You must call this method
  /// before calling other methods.
  ///
  /// See:
  ///
  /// * [SignInInitParameters]
  Future<void> initWithParams(SignInInitParameters params) async {
    await init(
      scopes: params.scopes,
      signInOption: params.signInOption,
      hostedDomain: params.hostedDomain,
      clientId: params.clientId,
    );
  }

  /// Attempts to reuse pre-existing credentials to sign in again, without user interaction.
  Future<GoogleSignInUserData?> signInSilently() async {
    throw UnimplementedError('signInSilently() has not been implemented.');
  }

  /// Signs in the user with the options specified to [init].
  Future<GoogleSignInUserData?> signIn() async {
    throw UnimplementedError('signIn() has not been implemented.');
  }

  /// Returns the Tokens used to authenticate other API calls.
  Future<GoogleSignInTokenData> getTokens(
      {required String email, bool? shouldRecoverAuth}) async {
    throw UnimplementedError('getTokens() has not been implemented.');
  }

  /// Signs out the current account from the application.
  Future<void> signOut() async {
    throw UnimplementedError('signOut() has not been implemented.');
  }

  /// Revokes all of the scopes that the user granted.
  Future<void> disconnect() async {
    throw UnimplementedError('disconnect() has not been implemented.');
  }

  /// Returns whether the current user is currently signed in.
  Future<bool> isSignedIn() async {
    throw UnimplementedError('isSignedIn() has not been implemented.');
  }

  /// Clears any cached information that the plugin may be holding on to.
  Future<void> clearAuthCache({required String token}) async {
    throw UnimplementedError('clearAuthCache() has not been implemented.');
  }

  /// Requests the user grants additional Oauth [scopes].
  ///
  /// Scopes should come from the full  list
  /// [here](https://developers.google.com/identity/protocols/googlescopes).
  Future<bool> requestScopes(List<String> scopes) async {
    throw UnimplementedError('requestScopes() has not been implmented.');
  }
}
