// Copyright (c) 2023, the Dart 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:io' as io;

import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:file/memory.dart';
import 'package:http/http.dart';
import 'package:meta/meta.dart';

import 'asserts.dart';
import 'config_handler.dart';
import 'constants.dart';
import 'enums.dart';
import 'event.dart';
import 'ga_client.dart';
import 'initializer.dart';
import 'log_handler.dart';
import 'survey_handler.dart';
import 'user_property.dart';
import 'utils.dart';

abstract class Analytics {
  /// The default factory constructor that will return an implementation
  /// of the [Analytics] abstract class using the [LocalFileSystem].
  ///
  /// If [enableAsserts] is set to `true`, then asserts for GA4 limitations
  /// will be enabled.
  ///
  /// [flutterChannel] and [flutterVersion] are nullable in case the client
  /// using this package is unable to resolve those values.
  ///
  /// An optional parameter [clientIde] is also available for dart and flutter
  /// tooling that are running from IDEs can be resolved. Such as "VSCode"
  /// running the flutter-tool.
  ///
  /// [enabledFeatures] is also an optional field that can be added to collect
  /// any features that are enabled for a user. For example,
  /// "enable-linux-desktop,cli-animations" are two features that can be enabled
  /// for the flutter-tool.
  factory Analytics({
    required DashTool tool,
    required String dartVersion,
    String? flutterChannel,
    String? flutterVersion,
    String? clientIde,
    String? enabledFeatures,
    bool enableAsserts = false,
  }) {
    // Create the instance of the file system so clients don't need
    // resolve on their own
    const FileSystem fs = LocalFileSystem();

    // Ensure that the home directory has permissions enabled to write
    final homeDirectory = getHomeDirectory(fs);
    if (homeDirectory == null ||
        !checkDirectoryForWritePermissions(homeDirectory)) {
      return const NoOpAnalytics();
    }

    // Resolve the OS using dart:io
    final DevicePlatform platform;
    if (io.Platform.operatingSystem == 'linux') {
      platform = DevicePlatform.linux;
    } else if (io.Platform.operatingSystem == 'macos') {
      platform = DevicePlatform.macos;
    } else {
      platform = DevicePlatform.windows;
    }

    // Create the instance of the GA Client which will create
    // an [http.Client] to send requests
    final gaClient = GAClient(
      measurementId: kGoogleAnalyticsMeasurementId,
      apiSecret: kGoogleAnalyticsApiSecret,
    );

    final firstRun = runInitialization(homeDirectory: homeDirectory);

    return AnalyticsImpl(
      tool: tool,
      homeDirectory: homeDirectory,
      flutterChannel: flutterChannel,
      flutterVersion: flutterVersion,
      dartVersion: dartVersion,
      platform: platform,
      toolsMessageVersion: kToolsMessageVersion,
      fs: fs,
      gaClient: gaClient,
      surveyHandler: SurveyHandler(
        dismissedSurveyFile: homeDirectory
            .childDirectory(kDartToolDirectoryName)
            .childFile(kDismissedSurveyFileName),
      ),
      enableAsserts: enableAsserts,
      clientIde: clientIde,
      enabledFeatures: enabledFeatures,
      firstRun: firstRun,
    );
  }

  /// Factory constructor to return the [AnalyticsImpl] class with
  /// Google Analytics credentials that point to a test instance and
  /// not the production instance where live data will be sent.
  ///
  /// By default, [enableAsserts] is set to `true` to check against
  /// GA4 limitations.
  ///
  /// [flutterChannel] and [flutterVersion] are nullable in case the client
  /// using this package is unable to resolve those values.
  factory Analytics.development({
    required DashTool tool,
    required String dartVersion,
    String? flutterChannel,
    String? flutterVersion,
    String? clientIde,
    String? enabledFeatures,
    bool enableAsserts = true,
  }) {
    // Create the instance of the file system so clients don't need
    // resolve on their own
    const FileSystem fs = LocalFileSystem();

    // Ensure that the home directory has permissions enabled to write
    final homeDirectory = getHomeDirectory(fs);
    if (homeDirectory == null) {
      throw Exception('Unable to determine the home directory, '
          'ensure it is available in the environment');
    }
    if (!checkDirectoryForWritePermissions(homeDirectory)) {
      throw Exception('Permissions error on the home directory!');
    }

    // Resolve the OS using dart:io
    final DevicePlatform platform;
    if (io.Platform.operatingSystem == 'linux') {
      platform = DevicePlatform.linux;
    } else if (io.Platform.operatingSystem == 'macos') {
      platform = DevicePlatform.macos;
    } else {
      platform = DevicePlatform.windows;
    }

    // Credentials defined below for the test Google Analytics instance
    const kTestMeasurementId = 'G-N1NXG28J5B';
    const kTestApiSecret = '4yT8__oER3Cd84dtx6r-_A';

    // Create the instance of the GA Client which will create
    // an [http.Client] to send requests
    final gaClient = GAClient(
      measurementId: kTestMeasurementId,
      apiSecret: kTestApiSecret,
    );

    final firstRun = runInitialization(homeDirectory: homeDirectory);

    return AnalyticsImpl(
      tool: tool,
      homeDirectory: homeDirectory,
      flutterChannel: flutterChannel,
      flutterVersion: flutterVersion,
      dartVersion: dartVersion,
      platform: platform,
      toolsMessageVersion: kToolsMessageVersion,
      fs: fs,
      gaClient: gaClient,
      surveyHandler: SurveyHandler(
        dismissedSurveyFile: homeDirectory
            .childDirectory(kDartToolDirectoryName)
            .childFile(kDismissedSurveyFileName),
      ),
      enableAsserts: enableAsserts,
      clientIde: clientIde,
      enabledFeatures: enabledFeatures,
      firstRun: firstRun,
    );
  }

  /// The shared identifier for Flutter and Dart related tooling using
  /// package:unified_analytics.
  String get clientId;

  /// Retrieves the consent message to prompt users with on first
  /// run or when the message has been updated.
  String get getConsentMessage;

  /// Returns true if it is OK to send an analytics message. Do not cache,
  /// as this depends on factors that can change, such as the configuration
  /// file contents.
  bool get okToSend;

  /// Returns a map object with all of the tools that have been parsed
  /// out of the configuration file.
  Map<String, ToolInfo> get parsedTools;

  /// Boolean that lets the client know if they should display the message.
  bool get shouldShowMessage;

  /// Boolean indicating whether or not telemetry is enabled.
  bool get telemetryEnabled;

  /// Returns a map representation of the [UserProperty] for the [Analytics]
  /// instance.
  ///
  /// This is what will get sent to Google Analytics with every request.
  Map<String, Map<String, Object?>> get userPropertyMap;

  /// Method to be invoked by the client using this package to confirm
  /// that the client has shown the message and that it can be added to
  /// the config file and start sending events the next time it starts up.
  void clientShowedMessage();

  /// Call this method when the tool using this package is closed.
  ///
  /// Prevents the tool from hanging when if there are still requests
  /// that need to be sent off.
  ///
  /// Providing [delayDuration] in milliseconds will allow the instance
  /// to wait the provided time before closing the http connection. Keeping
  /// the connection open for some time will allow any pending events that
  /// are waiting to be sent to the Google Analytics server. Default value
  /// of 250 ms applied.
  Future<void> close({int delayDuration = kDelayDuration});

  /// Method to fetch surveys from the endpoint [kContextualSurveyUrl].
  ///
  /// Any survey that is returned by this method has already passed
  /// the survey conditions specified in the remote survey metadata file.
  ///
  /// If the method returns an empty list, then there are no surveys to be
  /// shared with the user.
  Future<List<Survey>> fetchAvailableSurveys();

  /// Query the persisted event data stored on the user's machine.
  ///
  /// Returns null if there are no persisted logs.
  LogFileStats? logFileStats();

  /// Send preconfigured events using specific named constructors
  /// on the [Event] class.
  ///
  /// Example
  /// ```dart
  /// analytics.send(Event.memory(periodSec: 123));
  /// ```
  void send(Event event);

  /// Pass a boolean to either enable or disable telemetry and make
  /// the necessary changes in the persisted configuration file.
  ///
  /// Setting the telemetry status will also send an event to GA
  /// indicating the latest status of the telemetry from [reportingBool].
  Future<void> setTelemetry(bool reportingBool);

  /// Calling this will result in telemetry collection being suppressed for
  /// the current invocation.
  ///
  /// If you would like to permanently disable telemetry
  /// collection use:
  ///
  /// ```dart
  /// analytics.setTelemetry(false)
  /// ```
  void suppressTelemetry();

  /// Method to run after interacting with a [Survey] instance.
  ///
  /// Pass a [Survey] instance which can be retrieved from
  /// [Analytics.fetchAvailableSurveys].
  ///
  /// [surveyButton] is the button that was interacted with by the user.
  void surveyInteracted({
    required Survey survey,
    required SurveyButton surveyButton,
  });

  /// Method to be called after a survey has been shown to the user.
  ///
  /// Calling this will snooze the survey so it won't be shown immediately.
  ///
  /// The snooze period is defined by the [Survey.snoozeForMinutes] field.
  void surveyShown(Survey survey);

  /// Returns an instance of [FakeAnalytics] which can be used in tests to check
  /// for certain [Event] instances within [FakeAnalytics.sentEvents].
  @visibleForTesting
  static FakeAnalytics fake({
    required DashTool tool,
    required Directory homeDirectory,
    required String dartVersion,
    required MemoryFileSystem fs,
    String? flutterChannel,
    String? flutterVersion,
    String? clientIde,
    String? enabledFeatures,
    SurveyHandler? surveyHandler,
    GAClient? gaClient,
    DevicePlatform platform = DevicePlatform.linux,
    int toolsMessageVersion = kToolsMessageVersion,
    String toolsMessage = kToolsMessage,
    bool enableAsserts = true,
  }) {
    final firstRun = runInitialization(homeDirectory: homeDirectory);

    return FakeAnalytics._(
      tool: tool,
      homeDirectory: homeDirectory,
      flutterChannel: flutterChannel,
      toolsMessageVersion: toolsMessageVersion,
      flutterVersion: flutterVersion,
      dartVersion: dartVersion,
      platform: platform,
      fs: fs,
      surveyHandler: surveyHandler ??
          FakeSurveyHandler.fromList(
            dismissedSurveyFile: homeDirectory
                .childDirectory(kDartToolDirectoryName)
                .childFile(kDismissedSurveyFileName),
            initializedSurveys: [],
          ),
      gaClient: gaClient ?? const FakeGAClient(),
      clientIde: clientIde,
      enabledFeatures: enabledFeatures,
      firstRun: firstRun,
      enableAsserts: enableAsserts,
    );
  }
}

class AnalyticsImpl implements Analytics {
  final DashTool tool;
  final FileSystem fs;
  final int toolsMessageVersion;
  final ConfigHandler _configHandler;
  final GAClient _gaClient;
  final SurveyHandler _surveyHandler;
  final File _clientIdFile;
  final UserProperty _userProperty;
  final LogHandler _logHandler;
  final String? _enabledFeatures;

  /// Tells the client if they need to show a message to the
  /// user; this will return true if it is the first time the
  /// package is being used for a developer or if the consent
  /// message has been updated by the package.
  bool _showMessage = false;

  /// When set to `true`, various assert statements will be enabled
  /// to ensure usage of this class is within GA4 limitations.
  final bool _enableAsserts;

  /// Telemetry suppression flag that is set via [Analytics.suppressTelemetry].
  bool _telemetrySuppressed = false;

  /// Indicates if this is the first run for a given tool.
  bool _firstRun = false;

  /// The list of futures that will contain all of the send events
  /// from the [GAClient].
  final _futures = <Future<Response>>[];

  /// Internal value for the client id which will be lazily loaded.
  String? _clientId;

  /// Internal collection of [Event]s that have been sent
  /// for errors encountered within package:unified_analytics.
  ///
  /// Stores each of the events that have been sent to GA4 so that the
  /// same error doesn't get sent twice.
  final Set<Event> _sentErrorEvents = {};

  AnalyticsImpl({
    required this.tool,
    required Directory homeDirectory,
    required String? flutterChannel,
    required String? flutterVersion,
    required String? clientIde,
    required String? enabledFeatures,
    required String dartVersion,
    required DevicePlatform platform,
    required this.toolsMessageVersion,
    required this.fs,
    required GAClient gaClient,
    required SurveyHandler surveyHandler,
    required bool enableAsserts,
    required bool firstRun,
  })  : _gaClient = gaClient,
        _surveyHandler = surveyHandler,
        _enableAsserts = enableAsserts,
        _clientIdFile = homeDirectory
            .childDirectory(kDartToolDirectoryName)
            .childFile(kClientIdFileName),
        _userProperty = UserProperty(
          sessionFile: homeDirectory
              .childDirectory(kDartToolDirectoryName)
              .childFile(kSessionFileName),
          flutterChannel: flutterChannel,
          host: platform.label,
          flutterVersion: flutterVersion,
          dartVersion: dartVersion,
          tool: tool.label,
          // We truncate this to a maximum of 36 characters since this can
          // a very long string for some operating systems
          hostOsVersion:
              truncateStringToLength(io.Platform.operatingSystemVersion, 36),
          locale: io.Platform.localeName,
          clientIde: clientIde,
        ),
        _enabledFeatures = enabledFeatures,
        _configHandler = ConfigHandler(
          homeDirectory: homeDirectory,
          configFile: homeDirectory
              .childDirectory(kDartToolDirectoryName)
              .childFile(kConfigFileName),
        ),
        _logHandler = LogHandler(
          logFile: homeDirectory
              .childDirectory(kDartToolDirectoryName)
              .childFile(kLogFileName),
        ) {
    // This initializer class will let the instance know
    // if it was the first run; if it is, nothing will be sent
    // on the first run
    if (firstRun) {
      _showMessage = true;
      _firstRun = true;
    } else {
      _showMessage = false;
      _firstRun = false;
    }

    // Check if the tool has already been onboarded, and if it
    // has, check if the latest message version is greater to
    // prompt the client to show a message
    //
    // If the tool has not been added to the config file, then
    // we will show the message as well
    final currentVersion =
        _configHandler.parsedTools[tool.label]?.versionNumber ?? -1;
    if (currentVersion < toolsMessageVersion) {
      _showMessage = true;

      // If the message version has been updated, it will be considered
      // as if it was a first run and any events attempting to get sent
      // will be blocked
      _firstRun = true;
    }
  }

  @override
  String get clientId {
    if (!_clientIdFile.existsSync()) {
      createClientIdFile(clientIdFile: _clientIdFile);
    }
    _clientId ??= _clientIdFile.readAsStringSync();

    return _clientId!;
  }

  @override
  String get getConsentMessage {
    // The command to swap in the consent message
    final commandString =
        tool == DashTool.flutterTool || tool == DashTool.devtools
            ? 'flutter'
            : 'dart';

    return kToolsMessage
        .replaceAll('{{ toolDescription }}', tool.description)
        .replaceAll('{{ toolName }}', commandString);
  }

  /// Checking the [telemetryEnabled] boolean reflects what the
  /// config file reflects.
  ///
  /// Checking the [_showMessage] boolean indicates if the consent
  /// message has been shown for the user, this boolean is set to `true`
  /// when the tool using this package invokes the [clientShowedMessage]
  /// method.
  ///
  /// If the user has suppressed telemetry [_telemetrySuppressed] will
  /// return `true` to prevent events from being sent for current invocation.
  ///
  /// Checking if it is the first time a tool is running with this package
  /// as indicated by [_firstRun].
  @override
  bool get okToSend =>
      telemetryEnabled && !_showMessage && !_telemetrySuppressed && !_firstRun;

  @override
  Map<String, ToolInfo> get parsedTools => _configHandler.parsedTools;

  @override
  bool get shouldShowMessage => _showMessage;

  @override
  bool get telemetryEnabled => _configHandler.telemetryEnabled;

  @override
  Map<String, Map<String, Object?>> get userPropertyMap =>
      _userProperty.preparePayload();

  @override
  void clientShowedMessage() {
    // Check the tool needs to be added to the config file
    if (!_configHandler.parsedTools.containsKey(tool.label)) {
      _configHandler.addTool(
        tool: tool.label,
        versionNumber: toolsMessageVersion,
      );
    }

    // When the tool already exists but the consent message version
    // has been updated
    if (_configHandler.parsedTools[tool.label]!.versionNumber <
        toolsMessageVersion) {
      _configHandler.incrementToolVersion(
        tool: tool.label,
        newVersionNumber: toolsMessageVersion,
      );
    }
    _showMessage = false;
  }

  @override
  Future<void> close({int delayDuration = kDelayDuration}) async {
    // Collect any errors encountered and send
    _sendPendingErrorEvents();

    await Future.wait(_futures).timeout(
      Duration(milliseconds: delayDuration),
      onTimeout: () => [],
    );
    _gaClient.close();
  }

  @override
  Future<List<Survey>> fetchAvailableSurveys() async {
    final surveysToShow = <Survey>[];
    if (!okToSend) return surveysToShow;

    final logFileStats = _logHandler.logFileStats();

    // Call for surveys that have already been dismissed from
    // persisted survey ids on disk
    final persistedSurveyMap = _surveyHandler.fetchPersistedSurveys();

    for (final survey in await _surveyHandler.fetchSurveyList()) {
      // If the survey has listed the tool running this package in the exclude
      // list, it will not be returned
      if (survey.excludeDashToolList.contains(tool)) continue;

      // Apply the survey's sample rate; if the generated value from
      // the client id and survey's uniqueId are less, it will not get
      // sent to the user
      if (survey.samplingRate < sampleRate(clientId, survey.uniqueId)) {
        continue;
      }

      // If the survey has been permanently dismissed or has temporarily
      // been snoozed, skip it
      if (surveySnoozedOrDismissed(survey, persistedSurveyMap)) continue;

      // Counter to check each survey condition, if all are met, then
      // this integer will be equal to the number of conditions in
      // [Survey.conditionList]
      var conditionsMet = 0;
      if (logFileStats != null) {
        for (final condition in survey.conditionList) {
          // Retrieve the value from the [LogFileStats] with
          // the label provided in the condtion
          final logFileStatsValue =
              logFileStats.getValueByString(condition.field);

          if (logFileStatsValue == null) continue;

          switch (condition.operatorString) {
            case '>=':
              if (logFileStatsValue >= condition.value) conditionsMet++;
            case '<=':
              if (logFileStatsValue <= condition.value) conditionsMet++;
            case '>':
              if (logFileStatsValue > condition.value) conditionsMet++;
            case '<':
              if (logFileStatsValue < condition.value) conditionsMet++;
            case '==':
              if (logFileStatsValue == condition.value) conditionsMet++;
            case '!=':
              if (logFileStatsValue != condition.value) conditionsMet++;
          }
        }
      }

      if (conditionsMet == survey.conditionList.length) {
        surveysToShow.add(survey);
      }
    }

    return surveysToShow;
  }

  @override
  LogFileStats? logFileStats() => _logHandler.logFileStats();

  @override
  void send(Event event) {
    if (!okToSend) return;

    // Construct the body of the request
    final body = generateRequestBody(
      clientId: clientId,
      eventName: event.eventName,
      eventData: event.eventData,
      userProperty: _userProperty,
      enabledFeatures: _enabledFeatures,
    );

    if (_enableAsserts) checkBody(body);

    _logHandler.save(data: body);

    final gaClientFuture = _gaClient.sendData(body);
    _futures.add(gaClientFuture);
    gaClientFuture.whenComplete(() => _futures.remove(gaClientFuture));
  }

  @override
  Future<void> setTelemetry(bool reportingBool) {
    _configHandler.setTelemetry(reportingBool);

    // Creation of the [Event] for opting out
    final collectionEvent =
        Event.analyticsCollectionEnabled(status: reportingBool);

    // The body of the request that will be sent to GA4
    final Map<String, Object?> body;

    if (reportingBool) {
      // Recreate the session and client id file; no need to
      // recreate the log file since it will only receives events
      // to persist from events sent
      createClientIdFile(clientIdFile: _clientIdFile);
      createSessionFile(sessionFile: _userProperty.sessionFile);

      // Reread the client ID string so an empty string is not being
      // sent to GA4 since the persisted files are cleared when a user
      // decides to opt out of telemetry collection
      _clientId = _clientIdFile.readAsStringSync();

      // We must construct the body at this point after we have read in the
      // new client id string that was generated
      body = generateRequestBody(
        clientId: clientId,
        eventName: collectionEvent.eventName,
        eventData: collectionEvent.eventData,
        userProperty: _userProperty,
        enabledFeatures: _enabledFeatures,
      );

      _logHandler.save(data: body);
    } else {
      // Construct the body of the request to signal
      // telemetry status toggling
      body = generateRequestBody(
        clientId: clientId,
        eventName: collectionEvent.eventName,
        eventData: collectionEvent.eventData,
        enabledFeatures: _enabledFeatures,
        userProperty: _userProperty,
      );

      // For opted out users, data in the persisted files is cleared
      _userProperty.sessionFile.writeAsStringSync('');
      _logHandler.logFile.writeAsStringSync('');
      _clientIdFile.writeAsStringSync('');

      _clientId = '';
    }

    // Pass to the google analytics client to send with a
    // timeout incase http clients hang
    return _gaClient.sendData(body).timeout(
          const Duration(milliseconds: kDelayDuration),
          onTimeout: () => Response('', 200),
        );
  }

  @override
  void suppressTelemetry() => _telemetrySuppressed = true;

  @override
  void surveyInteracted({
    required Survey survey,
    required SurveyButton surveyButton,
  }) {
    // Any action, except for 'snooze' will permanently dismiss a given survey
    final permanentlyDismissed = surveyButton.action == 'snooze' ? false : true;
    _surveyHandler.dismiss(survey, permanentlyDismissed);
    send(Event.surveyAction(
      surveyId: survey.uniqueId,
      status: surveyButton.action,
    ));
  }

  @override
  void surveyShown(Survey survey) {
    _surveyHandler.dismiss(survey, false);
    send(Event.surveyShown(surveyId: survey.uniqueId));
  }

  /// Send any pending error events, useful for tests to avoid closing
  /// the connection.
  ///
  /// In the main implementation, [AnalyticsImpl], error events are only
  /// sent on exit when [close] is invoked. This helper method can instead
  /// have those error events sent immediately to help with tests that check
  /// [FakeAnalytics.sentEvents].
  void _sendPendingErrorEvents() {
    // Collect any errors encountered and send
    final errorEvents = {..._userProperty.errorSet, ..._logHandler.errorSet};
    errorEvents
        .where((event) =>
            event.eventName == DashEvent.analyticsException &&
            !_sentErrorEvents.contains(event))
        .forEach(send);

    // Ensure the same event doesn't get sent again
    _sentErrorEvents.addAll(errorEvents);

    // Clear error sets
    _userProperty.errorSet.clear();
    _logHandler.errorSet.clear();
  }
}

/// This fake instance of [Analytics] is intended to be used by clients of
/// this package for testing purposes. It exposes a list [sentEvents] that
/// keeps track of all events that have been sent.
///
/// This is useful for confirming that events are being sent for a given
/// workflow. Invoking the [send] method on this instance will not make any
/// network requests to Google Analytics.
class FakeAnalytics extends AnalyticsImpl {
  /// Use this list to check for events that have been emitted when
  /// invoking the send method
  final List<Event> sentEvents = [];

  /// Class to use when you want to see which events were sent
  FakeAnalytics._({
    required super.tool,
    required super.homeDirectory,
    required super.dartVersion,
    required super.platform,
    required super.fs,
    required super.surveyHandler,
    required super.firstRun,
    super.flutterChannel,
    super.flutterVersion,
    super.clientIde,
    super.enabledFeatures,
    super.toolsMessageVersion = kToolsMessageVersion,
    super.gaClient = const FakeGAClient(),
    super.enableAsserts = true,
  });

  /// Getter to reference the private [UserProperty].
  UserProperty get userProperty => _userProperty;

  @override
  void send(Event event) {
    if (!okToSend) return;

    // Construct the body of the request
    final body = generateRequestBody(
      clientId: clientId,
      eventName: event.eventName,
      eventData: event.eventData,
      userProperty: _userProperty,
      enabledFeatures: _enabledFeatures,
    );

    if (_enableAsserts) checkBody(body);

    _logHandler.save(data: body);

    // Using this list to validate that events are being sent
    // for internal methods in the `Analytics` instance
    sentEvents.add(event);
  }

  /// Public instance method to invoke private method that sends any
  /// pending error events.
  ///
  /// If this is never invoked, any pending error events will be sent
  /// when invoking the [close] method.
  void sendPendingErrorEvents() => _sendPendingErrorEvents();
}

/// An implementation that will never send events.
///
/// This is for clients that opt to either not send analytics, or will migrate
/// to use [AnalyticsImpl] at a later time.
class NoOpAnalytics implements Analytics {
  /// The hard-coded client ID value for each NoOp instance.
  static String get staticClientId => 'xxxx-xxxx';

  @override
  final String getConsentMessage = '';

  @override
  final bool okToSend = false;

  @override
  final Map<String, ToolInfo> parsedTools = const <String, ToolInfo>{};

  @override
  final bool shouldShowMessage = false;

  @override
  final bool telemetryEnabled = false;

  @override
  final Map<String, Map<String, Object?>> userPropertyMap =
      const <String, Map<String, Object?>>{};

  const NoOpAnalytics();

  @override
  String get clientId => staticClientId;

  @override
  void clientShowedMessage() {}

  @override
  Future<void> close({int delayDuration = kDelayDuration}) async {}

  @override
  Future<List<Survey>> fetchAvailableSurveys() async => const <Survey>[];

  @override
  LogFileStats? logFileStats() => null;

  @override
  Future<Response>? send(Event event) => null;

  @override
  Future<void> setTelemetry(bool reportingBool) async {}

  @override
  void suppressTelemetry() {}

  @override
  void surveyInteracted({
    required Survey survey,
    required SurveyButton surveyButton,
  }) {}

  @override
  void surveyShown(Survey survey) {}
}
