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

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_sign_in/google_sign_in.dart';

/// A instantiable class that extends [GoogleIdentity]
class _TestGoogleIdentity extends GoogleIdentity {
  _TestGoogleIdentity({
    required this.id,
    required this.email,
    this.photoUrl,
  });

  final String id;
  final String email;

  final String? photoUrl;

  @override
  String? get displayName => null;

  @override
  String? get serverAuthCode => null;
}

/// A mocked [HttpClient] which always returns a [_MockHttpRequest].
class _MockHttpClient extends Fake implements HttpClient {
  @override
  bool autoUncompress = true;

  @override
  Future<HttpClientRequest> getUrl(Uri url) {
    return Future<HttpClientRequest>.value(_MockHttpRequest());
  }
}

/// A mocked [HttpClientRequest] which always returns a [_MockHttpClientResponse].
class _MockHttpRequest extends Fake implements HttpClientRequest {
  @override
  Future<HttpClientResponse> close() {
    return Future<HttpClientResponse>.value(_MockHttpResponse());
  }
}

/// Arbitrary valid image returned by the [_MockHttpResponse].
///
/// This is an transparent 1x1 gif image.
/// It doesn't have to match the placeholder used in [GoogleUserCircleAvatar].
///
/// Those bytes come from `resources/transparentImage.gif`.
final Uint8List _transparentImage = Uint8List.fromList(
  [
    0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00, //
    0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x21, 0xf9, 0x04, 0x01, 0x00, //
    0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, //
    0x00, 0x02, 0x01, 0x44, 0x00, 0x3B
  ],
);

/// A mocked [HttpClientResponse] which is empty and has a [statusCode] of 200
/// and returns valid image.
class _MockHttpResponse extends Fake implements HttpClientResponse {
  final Stream<Uint8List> _delegate =
      Stream<Uint8List>.value(_transparentImage);

  @override
  int get contentLength => -1;

  @override
  HttpClientResponseCompressionState get compressionState {
    return HttpClientResponseCompressionState.decompressed;
  }

  @override
  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
    return _delegate.listen(onData,
        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  int get statusCode => 200;
}

void main() {
  testWidgets('It should build the GoogleUserCircleAvatar successfully',
      (WidgetTester tester) async {
    final GoogleIdentity identity = _TestGoogleIdentity(
      email: 'email@email.com',
      id: 'userId',
      photoUrl: 'photoUrl',
    );
    tester.binding.window.physicalSizeTestValue = Size(100, 100);

    await HttpOverrides.runZoned(
      () async {
        await tester.pumpWidget(MaterialApp(
          home: SizedBox(
            height: 100,
            width: 100,
            child: GoogleUserCircleAvatar(
              identity: identity,
            ),
          ),
        ));
      },
      createHttpClient: (SecurityContext? c) => _MockHttpClient(),
    );
  });
}
