// 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:convert';

import 'package:clock/clock.dart';
import 'package:convert/convert.dart';
import 'package:file/file.dart';

import 'initializer.dart';
import 'utils.dart';

/// The regex pattern used to parse the disable analytics line.
const String telemetryFlagPattern = r'^reporting=([0|1]) *$';

/// The regex pattern used to parse the tools info
/// from the configuration file.
///
/// Example:
/// ```text
/// flutter-tool=2022-10-26,1
/// devtools=2022-11-26,1
/// ```
const String toolPattern =
    r'^([A-Za-z0-9]+[A-Za-z0-9_-]*)=([0-9]{4}-[0-9]{2}-[0-9]{2}),([0-9]+)$';

class ConfigHandler {
  /// Regex pattern implementation for matching a line in the config file.
  static RegExp telemetryFlagRegex =
      RegExp(telemetryFlagPattern, multiLine: true);
  static RegExp toolRegex = RegExp(toolPattern, multiLine: true);

  final Directory homeDirectory;
  final File configFile;

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

  DateTime configFileLastModified;

  /// Reporting enabled unless specified by user
  bool _telemetryEnabled = true;

  ConfigHandler({
    required this.homeDirectory,
    required this.configFile,
  }) : configFileLastModified = configFile.lastModifiedSync() {
    // Call the method to parse the contents of the config file when
    // this class is initialized
    parseConfig();
  }

  /// Returns the telemetry state from the config file.
  ///
  /// Method will reparse the config file if it detects that the
  /// last modified datetime is different from what was parsed when
  /// the class was initialized.
  bool get telemetryEnabled {
    if (configFileLastModified.isBefore(configFile.lastModifiedSync())) {
      parseConfig();
      configFileLastModified = configFile.lastModifiedSync();
    }

    return _telemetryEnabled;
  }

  /// Responsibe for the creation of the configuration line
  /// for the tool being passed in by the user and adding a
  /// [ToolInfo] object.
  void addTool({
    required String tool,
    required int versionNumber,
  }) {
    // Create the new instance of [ToolInfo] to be added
    // to the [parsedTools] map
    parsedTools[tool] = ToolInfo(
      lastRun: clock.now(),
      versionNumber: versionNumber,
    );

    // New string to be appended to the bottom of the configuration file
    // with a newline character for new tools to be added
    var newTool = '$tool=$dateStamp,$versionNumber\n';
    if (!configFile.readAsStringSync().endsWith('\n')) {
      newTool = '\n$newTool';
    }
    configFile.writeAsStringSync(newTool, mode: FileMode.append);
    configFileLastModified = configFile.lastModifiedSync();
  }

  /// Will increment the version number and update the date
  /// in the config file for the provided tool name while
  /// also incrementing the version number in [ToolInfo].
  void incrementToolVersion({
    required String tool,
    required int newVersionNumber,
  }) {
    if (!parsedTools.containsKey(tool)) {
      return;
    }

    // Read in the config file contents and use a regex pattern to
    // match the line for the current tool (ie. flutter-tools=2023-01-05,1)
    final configString = configFile.readAsStringSync();
    final pattern = '^($tool)=([0-9]{4}-[0-9]{2}-[0-9]{2}),([0-9]+)\$';

    final regex = RegExp(pattern, multiLine: true);
    final matches = regex.allMatches(configString);

    // If there isn't exactly one match for the given tool, that suggests the
    // file has been altered and needs to be reset
    if (matches.length != 1) {
      resetConfig();
      return;
    }

    // Construct the new tool line for the config line and replace it
    // in the original config string to prep for writing back out
    final newToolString = '$tool=$dateStamp,$newVersionNumber';
    final newConfigString = configString.replaceAll(regex, newToolString);
    configFile.writeAsStringSync(newConfigString);

    final toolInfo = parsedTools[tool];
    if (toolInfo == null) {
      return;
    }

    // Update the [ToolInfo] object for the current tool
    toolInfo.lastRun = clock.now();
    toolInfo.versionNumber = newVersionNumber;
  }

  /// Method responsible for reading in the config file stored on
  /// user's machine and parsing out the following: all the tools that
  /// have been logged in the file, the dates they were last run, and
  /// determining if telemetry is enabled by parsing the file.
  void parseConfig() {
    // Begin with the assumption that telemetry is always enabled
    _telemetryEnabled = true;

    // Read the configuration file as a string and run the two regex patterns
    // on it to get information around which tools have been parsed and whether
    // or not telemetry has been disabled by the user
    final configString = configFile.readAsStringSync();

    // Collect the tools logged in the configuration file
    toolRegex.allMatches(configString).forEach((RegExpMatch element) {
      // Extract the information relevant for the [ToolInfo] class
      final tool = element.group(1) as String;
      final lastRun = DateTime.parse(element.group(2) as String);
      final versionNumber = int.parse(element.group(3) as String);

      // Initialize an instance of the [ToolInfo] class to store
      // in the [parsedTools] map object
      parsedTools[tool] = ToolInfo(
        lastRun: lastRun,
        versionNumber: versionNumber,
      );
    });

    // Check for lines signaling that the user has disabled analytics,
    // if multiple lines are found, the more conservative value will be used
    telemetryFlagRegex.allMatches(configString).forEach((RegExpMatch element) {
      // Conditional for recording telemetry as being disabled
      if (element.group(1) == '0') {
        _telemetryEnabled = false;
      }
    });
  }

  /// This will reset the configuration file and clear the
  /// [parsedTools] map and trigger parsing the config again.
  void resetConfig() {
    createConfigFile(
      configFile: configFile,
      homeDirectory: homeDirectory,
    );
    parsedTools.clear();
    parseConfig();
  }

  /// Disables the reporting capabilities if [reportingBool] is set to `false`.
  Future<void> setTelemetry(bool reportingBool) async {
    final flag = reportingBool ? '1' : '0';
    final configString = await configFile.readAsString();

    final matches = telemetryFlagRegex.allMatches(configString);

    // If there isn't exactly one match for the reporting flag, that suggests
    // the file has been altered and needs to be reset
    if (matches.length != 1) {
      resetConfig();
      return;
    }

    final newTelemetryString = 'reporting=$flag';

    final newConfigString =
        configString.replaceAll(telemetryFlagRegex, newTelemetryString);

    await configFile.writeAsString(newConfigString);
    configFileLastModified = configFile.lastModifiedSync();

    _telemetryEnabled = reportingBool;
  }
}

class ToolInfo {
  DateTime lastRun;
  int versionNumber;

  ToolInfo({
    required this.lastRun,
    required this.versionNumber,
  });

  @override
  String toString() {
    return json.encode(<String, Object?>{
      'lastRun': FixedDateTimeFormatter('YYYY-MM-DD').encode(lastRun),
      'versionNumber': versionNumber,
    });
  }
}
