// Copyright 2014 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:file/memory.dart';
import 'package:flutter_tools/src/base/bot_detector.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/persistent_tool_state.dart';
import 'package:mockito/mockito.dart';
import 'package:quiver/testing/async.dart';

import '../../src/common.dart';
import '../../src/mocks.dart';

void main() {
  group('BotDetector', () {
    FakePlatform fakePlatform;
    MockStdio mockStdio;
    MockHttpClient mockHttpClient;
    MockHttpClientRequest mockHttpClientRequest;
    MockHttpHeaders mockHttpHeaders;
    BotDetector botDetector;
    PersistentToolState persistentToolState;

    setUp(() {
      fakePlatform = FakePlatform()..environment = <String, String>{};
      mockStdio = MockStdio();
      mockHttpClient = MockHttpClient();
      mockHttpClientRequest = MockHttpClientRequest();
      mockHttpHeaders = MockHttpHeaders();
      persistentToolState = PersistentToolState.test(
        directory: MemoryFileSystem.test().currentDirectory,
        logger: BufferLogger.test(),
      );
      botDetector = BotDetector(
        platform: fakePlatform,
        httpClientFactory: () => mockHttpClient,
        persistentToolState: persistentToolState,
      );
    });

    group('isRunningOnBot', () {
      testWithoutContext('returns false unconditionally if BOT=false is set', () async {
        fakePlatform.environment['BOT'] = 'false';
        fakePlatform.environment['TRAVIS'] = 'true';

        expect(await botDetector.isRunningOnBot, isFalse);
        expect(persistentToolState.isRunningOnBot, isFalse);
      });

      testWithoutContext('returns false unconditionally if FLUTTER_HOST is set', () async {
        fakePlatform.environment['FLUTTER_HOST'] = 'foo';
        fakePlatform.environment['TRAVIS'] = 'true';

        expect(await botDetector.isRunningOnBot, isFalse);
        expect(persistentToolState.isRunningOnBot, isFalse);
      });

      testWithoutContext('returns false with and without a terminal attached', () async {
        when(mockHttpClient.getUrl(any)).thenAnswer((_) {
          throw const SocketException('HTTP connection timed out');
        });
        mockStdio.stdout.hasTerminal = true;
        expect(await botDetector.isRunningOnBot, isFalse);
        mockStdio.stdout.hasTerminal = false;
        expect(await botDetector.isRunningOnBot, isFalse);
        expect(persistentToolState.isRunningOnBot, isFalse);
      });

      testWithoutContext('can test analytics outputs on bots when outputting to a file', () async {
        fakePlatform.environment['TRAVIS'] = 'true';
        fakePlatform.environment['FLUTTER_ANALYTICS_LOG_FILE'] = '/some/file';
        expect(await botDetector.isRunningOnBot, isFalse);
        expect(persistentToolState.isRunningOnBot, isFalse);
      });

      testWithoutContext('returns true when azure metadata is reachable', () async {
        when(mockHttpClient.getUrl(any)).thenAnswer((_) {
          return Future<HttpClientRequest>.value(mockHttpClientRequest);
        });
        when(mockHttpClientRequest.headers).thenReturn(mockHttpHeaders);

        expect(await botDetector.isRunningOnBot, isTrue);
        expect(persistentToolState.isRunningOnBot, isTrue);
      });

      testWithoutContext('caches azure bot detection results across instances', () async {
        when(mockHttpClient.getUrl(any)).thenAnswer((_) {
          return Future<HttpClientRequest>.value(mockHttpClientRequest);
        });
        when(mockHttpClientRequest.headers).thenReturn(mockHttpHeaders);

        expect(await botDetector.isRunningOnBot, isTrue);
        expect(await BotDetector(
          platform: fakePlatform,
          httpClientFactory: () => mockHttpClient,
          persistentToolState: persistentToolState,
        ).isRunningOnBot, isTrue);
        verify(mockHttpClient.getUrl(any)).called(1);
      });

      testWithoutContext('returns true when running on borg', () async {
        fakePlatform.environment['BORG_ALLOC_DIR'] = 'true';

        expect(await botDetector.isRunningOnBot, isTrue);
        expect(persistentToolState.isRunningOnBot, isTrue);
      });
    });
  });

  group('AzureDetector', () {
    AzureDetector azureDetector;
    MockHttpClient mockHttpClient;
    MockHttpClientRequest mockHttpClientRequest;
    MockHttpHeaders mockHttpHeaders;

    setUp(() {
      mockHttpClient = MockHttpClient();
      mockHttpClientRequest = MockHttpClientRequest();
      mockHttpHeaders = MockHttpHeaders();
      azureDetector = AzureDetector(
        httpClientFactory: () => mockHttpClient,
      );
    });

    testWithoutContext('isRunningOnAzure returns false when connection times out', () async {
      when(mockHttpClient.getUrl(any)).thenAnswer((_) {
        throw const SocketException('HTTP connection timed out');
      });

      expect(await azureDetector.isRunningOnAzure, isFalse);
    });

    testWithoutContext('isRunningOnAzure returns false when the http request times out', () {
      FakeAsync().run((FakeAsync time) async {
        when(mockHttpClient.getUrl(any)).thenAnswer((_) {
          final Completer<HttpClientRequest> completer = Completer<HttpClientRequest>();
          return completer.future;  // Never completed to test timeout behavior.
        });
        final Future<bool> onBot = azureDetector.isRunningOnAzure;
        time.elapse(const Duration(seconds: 2));

        expect(await onBot, isFalse);
      });
    });

    testWithoutContext('isRunningOnAzure returns true when azure metadata is reachable', () async {
      when(mockHttpClient.getUrl(any)).thenAnswer((_) {
        return Future<HttpClientRequest>.value(mockHttpClientRequest);
      });
      when(mockHttpClientRequest.headers).thenReturn(mockHttpHeaders);

      expect(await azureDetector.isRunningOnAzure, isTrue);
    });
  });
}

class MockHttpClient extends Mock implements HttpClient {}
class MockHttpClientRequest extends Mock implements HttpClientRequest {}
class MockHttpHeaders extends Mock implements HttpHeaders {}
