// 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 'package:unified_analytics/unified_analytics.dart';

import '../base/config.dart';
import '../base/io.dart';
import '../features.dart';
import '../globals.dart' as globals;
import '../version.dart';

/// This function is called from within the context runner to perform
/// checks that are necessary for determining if a no-op version of
/// [Analytics] gets returned.
///
/// When [enableAsserts] is set to `true`, various assert statements
/// will be enabled to ensure usage of this class is within GA4 limitations.
///
/// For testing purposes, pass in a [FakeAnalytics] instance initialized with
/// an in-memory [FileSystem] to prevent writing to disk.
Analytics getAnalytics({
  required bool runningOnBot,
  required FlutterVersion flutterVersion,
  required Map<String, String> environment,
  required String? clientIde,
  required Config config,
  bool enableAsserts = false,
  FakeAnalytics? analyticsOverride,
}) {
  final String version = flutterVersion.getVersionString(redactUnknownBranches: true);
  final bool suppressEnvFlag = environment['FLUTTER_SUPPRESS_ANALYTICS']?.toLowerCase() == 'true';

  if (// Ignore local user branches.
      version.startsWith('[user-branch]') ||
      // Many CI systems don't do a full git checkout.
      version.endsWith('/unknown') ||
      // Ignore bots.
      runningOnBot ||
      // Ignore when suppressed by FLUTTER_SUPPRESS_ANALYTICS.
      suppressEnvFlag) {
    return NoOpAnalytics();
  }

  // Providing an override of the [Analytics] instance is preferred when
  // running tests for this function to prevent writing to the filesystem
  if (analyticsOverride != null) {
    return analyticsOverride;
  }

  return Analytics(
    tool: DashTool.flutterTool,
    flutterChannel: flutterVersion.channel,
    flutterVersion: flutterVersion.frameworkVersion,
    dartVersion: flutterVersion.dartSdkVersion,
    enableAsserts: enableAsserts,
    clientIde: clientIde,
    enabledFeatures: getEnabledFeatures(config),
  );
}

/// Uses the [Config] object to get enabled features.
String? getEnabledFeatures(Config config) {
  // Create string with all enabled features to send as user property
  final Iterable<Feature> enabledFeatures = allFeatures.where((Feature feature) {
    final String? configSetting = feature.configSetting;
    return configSetting != null && config.getValue(configSetting) == true;
  });
  return enabledFeatures.isNotEmpty
      ? enabledFeatures
          .map((Feature feature) => feature.configSetting)
          .join(',')
      : null;
}

/// Function to safely grab the max rss from [ProcessInfo].
int? getMaxRss(ProcessInfo processInfo) {
  try {
    return globals.processInfo.maxRss;
  } on Exception catch (error) {
    globals.printTrace('Querying maxRss failed with error: $error');
  }
  return null;
}
