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

import 'base/file_system.dart';

/// Processes dependencies into a string representing the NOTICES file.
///
/// Reads the NOTICES or LICENSE file from each package in the .packages file,
/// splitting each one into each component license so that it can be de-duped
/// if possible. If the NOTICES file exists, it is preferred over the LICENSE
/// file.
///
/// Individual licenses inside each LICENSE file should be separated by 80
/// hyphens on their own on a line.
///
/// If a LICENSE or NOTICES file contains more than one component license,
/// then each component license must start with the names of the packages to
/// which the component license applies, with each package name on its own line
/// and the list of package names separated from the actual license text by a
/// blank line. The packages need not match the names of the pub package. For
/// example, a package might itself contain code from multiple third-party
/// sources, and might need to include a license for each one.
class LicenseCollector {
  LicenseCollector({
    required FileSystem fileSystem
  }) : _fileSystem = fileSystem;

  final FileSystem _fileSystem;

  /// The expected separator for multiple licenses.
  static final String licenseSeparator = '\n' + ('-' * 80) + '\n';

  /// Obtain licenses from the `packageMap` into a single result.
  ///
  /// [additionalLicenses] should contain aggregated license files from all
  /// of the current applications dependencies.
  LicenseResult obtainLicenses(
    PackageConfig packageConfig,
    Map<String, List<File>> additionalLicenses,
  ) {
    final Map<String, Set<String>> packageLicenses = <String, Set<String>>{};
    final Set<String> allPackages = <String>{};
    final List<File> dependencies = <File>[];

    for (final Package package in packageConfig.packages) {
      final Uri packageUri = package.packageUriRoot;
      if (packageUri == null || packageUri.scheme != 'file') {
        continue;
      }
      // First check for NOTICES, then fallback to LICENSE
      File file = _fileSystem.file(packageUri.resolve('../NOTICES'));
      if (!file.existsSync()) {
        file = _fileSystem.file(packageUri.resolve('../LICENSE'));
      }
      if (!file.existsSync()) {
        continue;
      }

      dependencies.add(file);
      final List<String> rawLicenses = file
        .readAsStringSync()
        .split(licenseSeparator);
      for (final String rawLicense in rawLicenses) {
        List<String> packageNames = <String>[];
        String? licenseText;
        if (rawLicenses.length > 1) {
          final int split = rawLicense.indexOf('\n\n');
          if (split >= 0) {
            packageNames = rawLicense.substring(0, split).split('\n');
            licenseText = rawLicense.substring(split + 2);
          }
        }
        if (licenseText == null) {
          packageNames = <String>[package.name];
          licenseText = rawLicense;
        }
        packageLicenses.putIfAbsent(licenseText, () => <String>{}).addAll(packageNames);
        allPackages.addAll(packageNames);
      }
    }

    final List<String> combinedLicensesList = packageLicenses.keys
      .map<String>((String license) {
        final List<String> packageNames = packageLicenses[license]!.toList()
          ..sort();
        return packageNames.join('\n') + '\n\n' + license;
      }).toList();
    combinedLicensesList.sort();

    /// Append additional LICENSE files as specified in the pubspec.yaml.
    final List<String> additionalLicenseText = <String>[];
    final List<String> errorMessages = <String>[];
    for (final String package in additionalLicenses.keys) {
      for (final File license in additionalLicenses[package]!) {
        if (!license.existsSync()) {
          errorMessages.add(
            'package $package specified an additional license at ${license.path}, but this file '
            'does not exist.'
          );
          continue;
        }
        dependencies.add(license);
        try {
          additionalLicenseText.add(license.readAsStringSync());
        } on FormatException catch (err) {
          // File has an invalid encoding.
          errorMessages.add(
            'package $package specified an additional license at ${license.path}, but this file '
            'could not be read:\n$err'
          );
        } on FileSystemException catch (err) {
          // File cannot be parsed.
          errorMessages.add(
            'package $package specified an additional license at ${license.path}, but this file '
            'could not be read:\n$err'
          );
        }
      }
    }
    if (errorMessages.isNotEmpty) {
      return LicenseResult(
        combinedLicenses: '',
        dependencies: <File>[],
        errorMessages: errorMessages,
      );
    }

    final String combinedLicenses = combinedLicensesList
      .followedBy(additionalLicenseText)
      .join(licenseSeparator);

    return LicenseResult(
      combinedLicenses: combinedLicenses,
      dependencies: dependencies,
      errorMessages: errorMessages,
    );
  }
}

/// The result of processing licenses with a [LicenseCollector].
class LicenseResult {
  const LicenseResult({
    required this.combinedLicenses,
    required this.dependencies,
    required this.errorMessages,
  });

  /// The raw text of the consumed licenses.
  final String combinedLicenses;

  /// Each license file that was consumed as input.
  final List<File> dependencies;

  /// If non-empty, license collection failed and this messages should
  /// be displayed by the asset parser.
  final List<String> errorMessages;
}
