// 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.

// @dart = 2.8

import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/base/config.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build.dart';
import 'package:flutter_tools/src/commands/config.dart';
import 'package:flutter_tools/src/commands/doctor.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:test/fake.dart';
import 'package:usage/usage_io.dart';

import '../src/common.dart';
import '../src/context.dart';
import '../src/fakes.dart';
import '../src/test_flutter_command_runner.dart';

void main() {
  setUpAll(() {
    Cache.disableLocking();
  });

  group('analytics', () {
    Directory tempDir;
    Config testConfig;

    setUp(() {
      Cache.flutterRoot = '../..';
      tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_analytics_test.');
      testConfig = Config.test();
    });

    tearDown(() {
      tryToDelete(tempDir);
    });

    // Ensure we don't send anything when analytics is disabled.
    testUsingContext("doesn't send when disabled", () async {
      int count = 0;
      globals.flutterUsage.onSend.listen((Map<String, dynamic> data) => count++);

      final FlutterCommand command = FakeFlutterCommand();
      final CommandRunner<void>runner = createTestCommandRunner(command);

      globals.flutterUsage.enabled = false;
      await runner.run(<String>['fake']);
      expect(count, 0);

      globals.flutterUsage.enabled = true;
      await runner.run(<String>['fake']);
      // LogToFileAnalytics isFirstRun is hardcoded to false
      // so this usage will never act like the first run
      // (which would not send usage).
      expect(count, 4);

      count = 0;
      globals.flutterUsage.enabled = false;
      await runner.run(<String>['fake']);

      expect(count, 0);
    }, overrides: <Type, Generator>{
      FlutterVersion: () => FlutterVersion(),
      Usage: () => Usage(
        configDirOverride: tempDir.path,
        logFile: tempDir.childFile('analytics.log').path,
        runningOnBot: true,
      ),
    });

    // Ensure we don't send for the 'flutter config' command.
    testUsingContext("config doesn't send", () async {
      int count = 0;
      globals.flutterUsage.onSend.listen((Map<String, dynamic> data) => count++);

      globals.flutterUsage.enabled = false;
      final ConfigCommand command = ConfigCommand();
      final CommandRunner<void> runner = createTestCommandRunner(command);
      await runner.run(<String>['config']);
      expect(count, 0);

      globals.flutterUsage.enabled = true;
      await runner.run(<String>['config']);

      expect(count, 0);
    }, overrides: <Type, Generator>{
      FlutterVersion: () => FlutterVersion(),
      Usage: () => Usage(
        configDirOverride: tempDir.path,
        logFile: tempDir.childFile('analytics.log').path,
        runningOnBot: true,
      ),
    });

    testUsingContext('Usage records one feature in experiment setting', () async {
      testConfig.setValue(flutterWebFeature.configSetting, true);
      final Usage usage = Usage(runningOnBot: true);
      usage.sendCommand('test');

      final String featuresKey = cdKey(CustomDimensionsEnum.enabledFlutterFeatures);

      expect(globals.fs.file('test').readAsStringSync(), contains('$featuresKey: enable-web'));
    }, overrides: <Type, Generator>{
      FlutterVersion: () => FlutterVersion(),
      Config: () => testConfig,
      Platform: () => FakePlatform(environment: <String, String>{
        'FLUTTER_ANALYTICS_LOG_FILE': 'test',
      }),
      FileSystem: () => MemoryFileSystem.test(),
      ProcessManager: () => FakeProcessManager.any(),
    });

    testUsingContext('Usage records multiple features in experiment setting', () async {
      testConfig.setValue(flutterWebFeature.configSetting, true);
      testConfig.setValue(flutterLinuxDesktopFeature.configSetting, true);
      testConfig.setValue(flutterMacOSDesktopFeature.configSetting, true);
      final Usage usage = Usage(runningOnBot: true);
      usage.sendCommand('test');

      final String featuresKey = cdKey(CustomDimensionsEnum.enabledFlutterFeatures);

      expect(
        globals.fs.file('test').readAsStringSync(),
        contains('$featuresKey: enable-web,enable-linux-desktop,enable-macos-desktop'),
      );
    }, overrides: <Type, Generator>{
      FlutterVersion: () => FlutterVersion(),
      Config: () => testConfig,
      Platform: () => FakePlatform(environment: <String, String>{
        'FLUTTER_ANALYTICS_LOG_FILE': 'test',
      }),
      FileSystem: () => MemoryFileSystem.test(),
      ProcessManager: () => FakeProcessManager.any(),
    });
  });

  group('analytics with fakes', () {
    MemoryFileSystem memoryFileSystem;
    FakeStdio fakeStdio;
    TestUsage testUsage;
    FakeClock fakeClock;
    FakeDoctor doctor;

    setUp(() {
      memoryFileSystem = MemoryFileSystem.test();
      fakeStdio = FakeStdio();
      testUsage = TestUsage();
      fakeClock = FakeClock();
      doctor = FakeDoctor();
    });

    testUsingContext('flutter commands send timing events', () async {
      fakeClock.times = <int>[1000, 2000];
      doctor.diagnoseSucceeds = true;
      final DoctorCommand command = DoctorCommand();
      final CommandRunner<void> runner = createTestCommandRunner(command);
      await runner.run(<String>['doctor']);

      expect(testUsage.timings, contains(
        const TestTimingEvent(
            'flutter', 'doctor', Duration(milliseconds: 1000), label: 'success',
        ),
      ));
    }, overrides: <Type, Generator>{
      SystemClock: () => fakeClock,
      Doctor: () => doctor,
      Usage: () => testUsage,
    });

    testUsingContext('doctor fail sends warning', () async {
      fakeClock.times = <int>[1000, 2000];
      doctor.diagnoseSucceeds = false;
      final DoctorCommand command = DoctorCommand();
      final CommandRunner<void> runner = createTestCommandRunner(command);
      await runner.run(<String>['doctor']);


      expect(testUsage.timings, contains(
        const TestTimingEvent(
          'flutter', 'doctor', Duration(milliseconds: 1000), label: 'warning',
        ),
      ));
    }, overrides: <Type, Generator>{
      SystemClock: () => fakeClock,
      Doctor: () => doctor,
      Usage: () => testUsage,
    });

    testUsingContext('single command usage path', () async {
      final FlutterCommand doctorCommand = DoctorCommand();

      expect(await doctorCommand.usagePath, 'doctor');
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });

    testUsingContext('compound command usage path', () async {
      final BuildCommand buildCommand = BuildCommand();
      final FlutterCommand buildApkCommand = buildCommand.subcommands['apk'] as FlutterCommand;

      expect(await buildApkCommand.usagePath, 'build/apk');
    }, overrides: <Type, Generator>{
      Usage: () => testUsage,
    });

    testUsingContext('command sends localtime', () async {
      const int kMillis = 1000;
      fakeClock.times = <int>[kMillis];
      // Since FLUTTER_ANALYTICS_LOG_FILE is set in the environment, analytics
      // will be written to a file.
      final Usage usage = Usage(
        versionOverride: 'test',
        runningOnBot: true,
      );
      usage.suppressAnalytics = false;
      usage.enabled = true;

      usage.sendCommand('test');

      final String log = globals.fs.file('analytics.log').readAsStringSync();
      final DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(kMillis);

      expect(log.contains(formatDateTime(dateTime)), isTrue);
    }, overrides: <Type, Generator>{
      FileSystem: () => memoryFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      SystemClock: () => fakeClock,
      Platform: () => FakePlatform(
        environment: <String, String>{
          'FLUTTER_ANALYTICS_LOG_FILE': 'analytics.log',
        },
      ),
      Stdio: () => fakeStdio,
    });

    testUsingContext('event sends localtime', () async {
      const int kMillis = 1000;
      fakeClock.times = <int>[kMillis];
      // Since FLUTTER_ANALYTICS_LOG_FILE is set in the environment, analytics
      // will be written to a file.
      final Usage usage = Usage(
        versionOverride: 'test',
        runningOnBot: true,
      );
      usage.suppressAnalytics = false;
      usage.enabled = true;

      usage.sendEvent('test', 'test');

      final String log = globals.fs.file('analytics.log').readAsStringSync();
      final DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(kMillis);

      expect(log.contains(formatDateTime(dateTime)), isTrue);
    }, overrides: <Type, Generator>{
      FileSystem: () => memoryFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      SystemClock: () => fakeClock,
      Platform: () => FakePlatform(
        environment: <String, String>{
          'FLUTTER_ANALYTICS_LOG_FILE': 'analytics.log',
        },
      ),
      Stdio: () => fakeStdio,
    });
  });

  group('analytics bots', () {
    Directory tempDir;

    setUp(() {
      tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_analytics_bots_test.');
    });

    tearDown(() {
      tryToDelete(tempDir);
    });

    testUsingContext("don't send on bots with unknown version", () async {
      int count = 0;
      globals.flutterUsage.onSend.listen((Map<String, dynamic> data) => count++);
      await createTestCommandRunner().run(<String>['--version']);

      expect(count, 0);
    }, overrides: <Type, Generator>{
      Usage: () => Usage(
        settingsName: 'flutter_bot_test',
        versionOverride: 'dev/unknown',
        configDirOverride: tempDir.path,
        runningOnBot: false,
      ),
    });

    testUsingContext("don't send on bots even when opted in", () async {
      int count = 0;
      globals.flutterUsage.onSend.listen((Map<String, dynamic> data) => count++);
      globals.flutterUsage.enabled = true;
      await createTestCommandRunner().run(<String>['--version']);

      expect(count, 0);
    }, overrides: <Type, Generator>{
      Usage: () => Usage(
        settingsName: 'flutter_bot_test',
        versionOverride: 'dev/unknown',
        configDirOverride: tempDir.path,
        runningOnBot: false,
      ),
    });

    testUsingContext('Uses AnalyticsMock when .flutter cannot be created', () async {
      final Usage usage = Usage(
        settingsName: 'flutter_bot_test',
        versionOverride: 'dev/known',
        configDirOverride: tempDir.path,
        analyticsIOFactory: throwingAnalyticsIOFactory,
        runningOnBot: false,
      );
      final AnalyticsMock analyticsMock = AnalyticsMock();

      expect(usage.clientId, analyticsMock.clientId);
      expect(usage.suppressAnalytics, isTrue);
    });
  });
}

Analytics throwingAnalyticsIOFactory(
  String trackingId,
  String applicationName,
  String applicationVersion, {
  String analyticsUrl,
  Directory documentDirectory,
}) {
  throw const FileSystemException('Could not create file');
}

class FakeFlutterCommand extends FlutterCommand {
  @override
  String get description => 'A fake command';

  @override
  String get name => 'fake';

  @override
  Future<FlutterCommandResult> runCommand() async {
    return FlutterCommandResult.success();
  }
}

class FakeDoctor extends Fake implements Doctor {
  bool diagnoseSucceeds = false;

  @override
  Future<bool> diagnose({
    bool androidLicenses = false,
    bool verbose = true,
    bool showColor = true,
    AndroidLicenseValidator androidLicenseValidator,
  }) async {
    return diagnoseSucceeds;
  }
}

class FakeClock extends Fake implements SystemClock {
  List<int> times = <int>[];

  @override
  DateTime now() {
    return DateTime.fromMillisecondsSinceEpoch(times.removeAt(0));
  }
}
