// Copyright 2024 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.

import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:path/path.dart' as p;
import 'package:yaml/yaml.dart';

/// This class contains config file related business logic for
/// [license_utils.dart].
///
/// The [LicenseConfig] reads in config data from a YAML file into an
/// object that can be used to update license headers.
///
/// The 'repo wide check' test in [license_utils_test.dart] runs this logic to
/// ensure that proper license headers are enforced.
///
/// It is also designed so that it be used by the dt command or
/// from a standalone script/application in the future.
///
/// Sample config file:
/// ```yaml
/// # sequence of license text strings that should be matched against at the top of a file and removed. <value>, which normally represents a date, will be stored.
/// remove_licenses:
///   - |-
///     // This is some <value> multiline license
///     // text that should be removed from the file.
///   - |-
///     /* This is other <value> multiline license
///     text that should be removed from the file. */
///   - |-
///     # This is more <value> multiline license
///     # text that should be removed from the file.
///   - |-
///     // This is some multiline license text to
///     // remove that does not contain a stored value.
/// # sequence of license text strings that should be added to the top of a file. <value> will be replaced.
/// add_licenses:
///   - |-
///     // This is some <value> multiline license
///     // text that should be added to the file.
///   - |-
///     # This is other <value> multiline license
///     # text that should be added to the file.
///   - |-
///     // This is some multiline license text to
///     // add that does not contain a stored value.
/// # defines which files should have license text added or updated.
/// update_paths:
///   # path(s) to recursively check for files to remove/add license
///   include:
///       - /repo_root
///   # path(s) to recursively check for files to ignore
///   exclude:
///     # exclude everything in the /repo_root/sub_dir1 directory
///     - /repo_root/sub_dir1/
///     # exclude the given files
///     - /repo_root/sub_dir2/exclude1.ext1
///     - /repo_root/sub_dir2/sub_dir3/exclude2.ext2
///   file_types:
///     # extension
///     ext1:
///       # one or more indices of remove_licenses to remove
///       remove:
///         - 0
///         - 1
///       # index of add_licenses to add
///       add: 0
///     ext2:
///       remove:
///         - 2
///       add: 1
/// ```
class LicenseConfig {
  /// Builds a [LicenseConfig] from the provided values.
  LicenseConfig({
    required this.removeLicenses,
    required this.addLicenses,
    required this.includePaths,
    required this.excludePaths,
    required this.fileTypes,
  });

  /// Reads the contents of the yaml [file] and parses it into a [LicenseConfig]
  /// object.
  factory LicenseConfig.fromYamlFile(File file) {
    final yamlString = file.readAsStringSync();
    final yamlDoc = loadYamlDocument(yamlString);
    final yaml = yamlDoc.contents as YamlMap;
    final updatePaths = yaml['update_paths'];

    return LicenseConfig(
      removeLicenses: yaml['remove_licenses'],
      addLicenses: yaml['add_licenses'],
      includePaths: updatePaths['include'],
      excludePaths: updatePaths['exclude'],
      fileTypes: updatePaths['file_types'],
    );
  }

  /// Sequence of license text strings that should be matched against at the top
  /// of a file and removed.
  final YamlList removeLicenses;

  /// Sequence of license text strings that should be added to the top of a
  /// file.
  final YamlList addLicenses;

  /// Path(s) to recursively check for file to remove/add license text
  final YamlList includePaths;

  /// Path(s) to recursively check for files to ignore
  final YamlList excludePaths;

  /// Contains the extension (without a '.') and the associated indices
  /// of [removeLicenses] to remove and index of [addLicenses] to add for the
  /// file type.
  final YamlMap fileTypes;

  /// Returns the list of indices for the given [ext] of [removeLicenses]
  /// containing the license text to remove if they exist or an empty YamlList.
  YamlList getRemoveIndicesForExtension(String ext) {
    final fileType = fileTypes[_removeDotFromExtension(ext)];
    if (fileType != null) {
      return fileType['remove'] as YamlList;
    }
    return YamlList();
  }

  /// Returns the index for the given [ext] of [addLicenses] containing the
  /// license text to add if it exists or -1.
  int getAddIndexForExtension(String ext) {
    final fileType = fileTypes[_removeDotFromExtension(ext)];
    if (fileType != null) {
      return fileType['add'];
    }
    return -1;
  }

  /// Returns whether the file should be excluded according to the config.
  bool shouldExclude(File file) {
    var included = false;
    for (final includePath in includePaths) {
      if (file.path.startsWith(includePath)) {
        included = true;
        break;
      }
    }
    var excluded = false;
    for (final excludePath in excludePaths) {
      if (file.path.startsWith(excludePath)) {
        excluded = true;
        break;
      }
    }
    return !included || excluded;
  }

  /// The config expects an extension without a starting dot, so remove
  /// any that might exist (e.g. in the extension that is returned by
  /// [p.extension]).
  String _removeDotFromExtension(String ext) {
    if (ext.startsWith('.') && ext.length > 1) {
      return ext.substring(1);
    }
    return ext;
  }
}

/// This class contains license update related business logic for
/// [license_utils.dart].
///
/// The [LicenseHeader] uses config data from [LicenseConfig] to update
/// license text in configured files.
class LicenseHeader {
  /// Processes the [file] for replacement information.
  ///
  /// If the [file] contains the given [existingLicenseText] within the first
  /// number of [byteCount] bytes, return a Record containing:
  /// - existingHeader: existing license header text
  /// - replacementHeader: replacement license header text
  ///
  /// If the file can't be read or no match is found, throws an exception.
  ///
  /// Note on stored values
  /// ---------------------
  /// Any instance of &lt;value&gt; in the replacement license text will be
  /// replaced with either:
  /// 1. the stored value parsed from the existing header
  /// 2. [defaultStoredValue], if no value is parsed
  /// 3. current year, if no [defaultStoredValue] is provided
  ///
  /// For now, only up to one stored value is supported.
  Future<({String existingHeader, String replacementHeader})>
  getReplacementInfo({
    required File file,
    required String existingLicenseText,
    required String replacementLicenseText,
    required int byteCount,
    String? defaultStoredValue,
  }) async {
    final stream = file
        .openRead(0, byteCount)
        .transform(utf8.decoder)
        .handleError(
          (e) =>
              throw StateError(
                'License header expected, but error reading $file - $e',
              ),
        );
    await for (final content in stream) {
      final storedName = _parseStoredName(replacementLicenseText);
      if (content.contains(existingLicenseText)) {
        // Return just the license headers for the simple case with no stored
        // value requested (i.e. content matches licenseText verbatim)
        replacementLicenseText = replacementLicenseText.replaceAll(
          '<$storedName>',
          defaultStoredValue ?? DateTime.now().year.toString(),
        );
        return (
          existingHeader: existingLicenseText,
          replacementHeader: replacementLicenseText,
        );
      }
      // Return a non-empty map for the case where there is a stored value
      // requested (i.e. when there is a '<value>' defined in the license text)
      return _processHeaders(
        storedName: storedName,
        existingLicenseText: existingLicenseText,
        replacementLicenseText: replacementLicenseText,
        content: content,
      );
    }
    throw StateError('License header could not be added to ${file.path}');
  }

  /// Returns a copy of the given [file] with the [existingHeader] replaced by
  /// the [replacementHeader].
  ///
  /// Reads and writes the entire file contents all at once, so performance may
  /// degrade for large files.
  File rewriteLicenseHeader({
    required File file,
    required String existingHeader,
    required String replacementHeader,
  }) {
    final rewrittenFile = File('${file.path}.tmp');
    final contents = file.readAsStringSync();
    final replacementContents = contents.replaceFirst(
      existingHeader,
      replacementHeader,
    );
    rewrittenFile.writeAsStringSync(replacementContents, flush: true);
    return rewrittenFile;
  }

  /// Returns a copy of the given [file] that is missing a license header
  /// with the [replacementHeader] added to the top.
  ///
  /// Reads and writes the entire file contents all at once, so performance may
  /// degrade for large files.
  File addLicenseHeader({
    required File file,
    required String replacementHeader,
  }) {
    final rewrittenFile = File('${file.path}.tmp');
    final contents = file.readAsStringSync();
    rewrittenFile.writeAsStringSync(
      '$replacementHeader${Platform.lineTerminator}$contents',
      flush: true,
    );
    return rewrittenFile;
  }

  /// Bulk update license headers for files in the [directory] as configured
  /// in the [config] and return a processed paths Record containing:
  /// - list of included paths
  /// - list of updated paths
  ///
  /// If [dryRun] is set, return the processed paths Record, but no files will
  /// be actually be updated.
  Future<({List<String> includedPaths, List<String> updatedPaths})> bulkUpdate({
    required Directory directory,
    required LicenseConfig config,
    bool dryRun = false,
  }) async {
    final includedPathsList = <String>[];
    final updatedPathsList = <String>[];
    final files =
        directory.listSync(recursive: true).whereType<File>().toList();
    for (final file in files) {
      if (!config.shouldExclude(file)) {
        includedPathsList.add(file.path);
        final extension = p.extension(file.path);
        final addIndex = config.getAddIndexForExtension(extension);
        if (addIndex == -1) {
          // skip if add index doesn't exist for extension
          continue;
        }
        final fileLength = file.lengthSync();
        const bufferSize = 20;
        final replacementLicenseText = config.addLicenses[addIndex];
        final byteCount = min(
          bufferSize + replacementLicenseText.length,
          fileLength,
        );
        var replacementInfo = await getReplacementInfo(
          file: file,
          existingLicenseText: replacementLicenseText,
          replacementLicenseText: replacementLicenseText,
          byteCount: byteCount as int,
        );
        if (replacementInfo.existingHeader.isNotEmpty &&
            replacementInfo.replacementHeader.isNotEmpty &&
            replacementInfo.existingHeader ==
                replacementInfo.replacementHeader) {
          // Do nothing if the replacement header is the same as the
          // existing header
          continue;
        }
        final removeIndices = config.getRemoveIndicesForExtension(extension);
        for (final removeIndex in removeIndices) {
          final existingLicenseText = config.removeLicenses[removeIndex];
          // Assume that the license text will be near the start of the file,
          // but add in some buffer.
          final byteCount = min(
            bufferSize + existingLicenseText.length,
            fileLength,
          );
          replacementInfo = await getReplacementInfo(
            file: file,
            existingLicenseText: existingLicenseText,
            replacementLicenseText: replacementLicenseText,
            byteCount: byteCount as int,
          );
          if (replacementInfo.existingHeader.isNotEmpty &&
              replacementInfo.replacementHeader.isNotEmpty) {
            // Case 1: Existing header needs to be replaced
            if (dryRun) {
              updatedPathsList.add(file.path);
            } else {
              final rewrittenFile = rewriteLicenseHeader(
                file: file,
                existingHeader: replacementInfo.existingHeader,
                replacementHeader: replacementInfo.replacementHeader,
              );
              _updateLicense(rewrittenFile, file, updatedPathsList);
            }
          }
        }
        if (!updatedPathsList.contains(file.path)) {
          final licenseHeaders = _processHeaders(
            storedName: _parseStoredName(replacementLicenseText),
            existingLicenseText: '',
            replacementLicenseText: replacementLicenseText,
            content: '',
          );
          if (licenseHeaders.replacementHeader.isNotEmpty) {
            // Case 2: Missing header needs to be added
            if (dryRun) {
              updatedPathsList.add(file.path);
            } else {
              final rewrittenFile = addLicenseHeader(
                file: file,
                replacementHeader: licenseHeaders.replacementHeader,
              );
              _updateLicense(rewrittenFile, file, updatedPathsList);
            }
          }
        }
      }
    }
    return (includedPaths: includedPathsList, updatedPaths: updatedPathsList);
  }

  void _updateLicense(
    File rewrittenFile,
    File file,
    List<String> updatedPathsList,
  ) {
    if (rewrittenFile.lengthSync() > 0) {
      file.writeAsStringSync(
        rewrittenFile.readAsStringSync(),
        mode: FileMode.writeOnly,
        flush: true,
      );
      updatedPathsList.add(file.path);
    }
    rewrittenFile.deleteSync();
  }

  ({String existingHeader, String replacementHeader}) _processHeaders({
    required String storedName,
    required String existingLicenseText,
    required String replacementLicenseText,
    required String content,
  }) {
    final matchStr = RegExp.escape(existingLicenseText);
    final storedNameIndex = matchStr.indexOf('<$storedName>');
    if (storedNameIndex != -1) {
      final beforeStoredName = matchStr.substring(0, storedNameIndex);
      final afterStoredName =
          matchStr
              .substring(storedNameIndex + storedName.length + 2)
              .trimRight();
      final storedMatcher = RegExp(
        r'' +
            beforeStoredName +
            r'((?<' +
            storedName +
            r'>\S+))' +
            afterStoredName,
      );
      if (storedMatcher.hasMatch(content)) {
        final match = storedMatcher.firstMatch(content);
        final existingHeaderValue = match?.group(0);
        final storedValue = match?.namedGroup(storedName);
        final replacementHeaderValue = replacementLicenseText.replaceAll(
          '<$storedName>',
          storedValue ?? DateTime.now().year.toString(),
        );
        return (
          existingHeader: existingHeaderValue ?? '',
          replacementHeader: replacementHeaderValue,
        );
      }
    }
    final defaultReplacementHeader = replacementLicenseText.replaceAll(
      '<$storedName>',
      DateTime.now().year.toString(),
    );
    return (existingHeader: '', replacementHeader: defaultReplacementHeader);
  }

  // TODO(mossmana) Add support for multiple stored names
  String _parseStoredName(String licenseText) {
    final storedMatch = RegExp(r'<(\S+)>').firstMatch(licenseText);
    final storedName = storedMatch?.group(1);
    return storedName ?? '';
  }
}
