// Copyright 2013 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:file/file.dart';
import 'package:git/git.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';

import 'common/core.dart';
import 'common/package_command.dart';

const Set<String> _codeFileExtensions = <String>{
  '.c',
  '.cc',
  '.cpp',
  '.dart',
  '.h',
  '.html',
  '.java',
  '.kt',
  '.m',
  '.mm',
  '.swift',
  '.sh',
};

// Basenames without extensions of files to ignore.
const Set<String> _ignoreBasenameList = <String>{
  'flutter_export_environment',
  'GeneratedPluginRegistrant',
  'generated_plugin_registrant',
};

// File suffixes that otherwise match _codeFileExtensions to ignore.
const Set<String> _ignoreSuffixList = <String>{
  '.g.dart', // Generated API code.
  '.mocks.dart', // Generated by Mockito.
};

// Full basenames of files to ignore.
const Set<String> _ignoredFullBasenameList = <String>{
  'resource.h', // Generated by VS.
};

// Copyright and license regexes for third-party code.
//
// These are intentionally very simple, since there is very little third-party
// code in this repository. Complexity can be added as-needed on a case-by-case
// basis.
//
// When adding license regexes here, include the copyright info to ensure that
// any new additions are flagged for added scrutiny in review.
final List<RegExp> _thirdPartyLicenseBlockRegexes = <RegExp>[
  // Third-party code used in url_launcher_web.
  RegExp(
    r'^// Copyright 2017 Workiva Inc\..*'
    r'^// Licensed under the Apache License, Version 2\.0',
    multiLine: true,
    dotAll: true,
  ),
  // Third-party code used in google_maps_flutter_web.
  RegExp(
    r'^// The MIT License [^C]+ Copyright \(c\) 2008 Krasimir Tsonev',
    multiLine: true,
  ),
  // bsdiff in flutter/packages.
  RegExp(
    r'// Copyright 2003-2005 Colin Percival\. All rights reserved\.\n'
    r'// Use of this source code is governed by a BSD-style license that can be\n'
    r'// found in the LICENSE file\.\n',
  ),
];

// The exact format of the BSD license that our license files should contain.
// Slight variants are not accepted because they may prevent consolidation in
// tools that assemble all licenses used in distributed applications.
// standardized.
const String _fullBsdLicenseText = '''
Copyright 2013 The Flutter Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.
    * Neither the name of Google Inc. nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''';

/// Validates that code files have copyright and license blocks.
class LicenseCheckCommand extends PackageCommand {
  /// Creates a new license check command for [packagesDir].
  LicenseCheckCommand(Directory packagesDir,
      {Platform platform = const LocalPlatform(), GitDir? gitDir})
      : super(packagesDir, platform: platform, gitDir: gitDir);

  @override
  final String name = 'license-check';

  @override
  final String description =
      'Ensures that all code files have copyright/license blocks.';

  @override
  Future<void> run() async {
    // Create a set of absolute paths to submodule directories, with trailing
    // separator, to do prefix matching with to test directory inclusion.
    final Iterable<String> submodulePaths = (await _getSubmoduleDirectories())
        .map(
            (Directory dir) => '${dir.absolute.path}${platform.pathSeparator}');

    final Iterable<File> allFiles = (await _getAllFiles()).where(
        (File file) => !submodulePaths.any(file.absolute.path.startsWith));

    final Iterable<File> codeFiles = allFiles.where((File file) =>
        _codeFileExtensions.contains(p.extension(file.path)) &&
        !_shouldIgnoreFile(file));
    final Iterable<File> firstPartyLicenseFiles = allFiles.where((File file) =>
        path.basename(file.basename) == 'LICENSE' && !_isThirdParty(file));

    final List<File> licenseFileFailures =
        await _checkLicenseFiles(firstPartyLicenseFiles);
    final Map<_LicenseFailureType, List<File>> codeFileFailures =
        await _checkCodeLicenses(codeFiles);

    bool passed = true;

    print('\n=======================================\n');

    if (licenseFileFailures.isNotEmpty) {
      passed = false;
      printError(
          'The following LICENSE files do not follow the expected format:');
      for (final File file in licenseFileFailures) {
        printError('  ${file.path}');
      }
      printError('Please ensure that they use the exact format used in this '
          'repository".\n');
    }

    if (codeFileFailures[_LicenseFailureType.incorrectFirstParty]!.isNotEmpty) {
      passed = false;
      printError('The license block for these files is missing or incorrect:');
      for (final File file
          in codeFileFailures[_LicenseFailureType.incorrectFirstParty]!) {
        printError('  ${file.path}');
      }
      printError(
          'If this third-party code, move it to a "third_party/" directory, '
          'otherwise ensure that you are using the exact copyright and license '
          'text used by all first-party files in this repository.\n');
    }

    if (codeFileFailures[_LicenseFailureType.unknownThirdParty]!.isNotEmpty) {
      passed = false;
      printError(
          'No recognized license was found for the following third-party files:');
      for (final File file
          in codeFileFailures[_LicenseFailureType.unknownThirdParty]!) {
        printError('  ${file.path}');
      }
      print('Please check that they have a license at the top of the file. '
          'If they do, the license check needs to be updated to recognize '
          'the new third-party license block.\n');
    }

    if (!passed) {
      throw ToolExit(1);
    }

    printSuccess('All files passed validation!');
  }

  // Creates the expected copyright+license block for first-party code.
  String _generateLicenseBlock(
    String comment, {
    String prefix = '',
    String suffix = '',
  }) {
    return '$prefix${comment}Copyright 2013 The Flutter Authors. All rights reserved.\n'
        '${comment}Use of this source code is governed by a BSD-style license that can be\n'
        '${comment}found in the LICENSE file.$suffix\n';
  }

  /// Checks all license blocks for [codeFiles], returning any that fail
  /// validation.
  Future<Map<_LicenseFailureType, List<File>>> _checkCodeLicenses(
      Iterable<File> codeFiles) async {
    final List<File> incorrectFirstPartyFiles = <File>[];
    final List<File> unrecognizedThirdPartyFiles = <File>[];

    // Most code file types in the repository use '//' comments.
    final String defaultFirstParyLicenseBlock = _generateLicenseBlock('// ');
    // A few file types have a different comment structure.
    final Map<String, String> firstPartyLicenseBlockByExtension =
        <String, String>{
      '.sh': _generateLicenseBlock('# '),
      '.html': _generateLicenseBlock('', prefix: '<!-- ', suffix: ' -->'),
    };

    for (final File file in codeFiles) {
      print('Checking ${file.path}');
      // On Windows, git may auto-convert line endings on checkout; this should
      // still pass since they will be converted back on commit.
      final String content =
          (await file.readAsString()).replaceAll('\r\n', '\n');

      final String firstParyLicense =
          firstPartyLicenseBlockByExtension[p.extension(file.path)] ??
              defaultFirstParyLicenseBlock;
      if (_isThirdParty(file)) {
        // Third-party directories allow either known third-party licenses, our
        // the first-party license, as there may be local additions.
        if (!_thirdPartyLicenseBlockRegexes
                .any((RegExp regex) => regex.hasMatch(content)) &&
            !content.contains(firstParyLicense)) {
          unrecognizedThirdPartyFiles.add(file);
        }
      } else {
        if (!content.contains(firstParyLicense)) {
          incorrectFirstPartyFiles.add(file);
        }
      }
    }

    // Sort by path for more usable output.
    int pathCompare(File a, File b) => a.path.compareTo(b.path);
    incorrectFirstPartyFiles.sort(pathCompare);
    unrecognizedThirdPartyFiles.sort(pathCompare);

    return <_LicenseFailureType, List<File>>{
      _LicenseFailureType.incorrectFirstParty: incorrectFirstPartyFiles,
      _LicenseFailureType.unknownThirdParty: unrecognizedThirdPartyFiles,
    };
  }

  /// Checks all provided LICENSE [files], returning any that fail validation.
  Future<List<File>> _checkLicenseFiles(Iterable<File> files) async {
    final List<File> incorrectLicenseFiles = <File>[];

    for (final File file in files) {
      print('Checking ${file.path}');
      // On Windows, git may auto-convert line endings on checkout; this should
      // still pass since they will be converted back on commit.
      final String contents = file.readAsStringSync().replaceAll('\r\n', '\n');
      if (!contents.contains(_fullBsdLicenseText)) {
        incorrectLicenseFiles.add(file);
      }
    }

    return incorrectLicenseFiles;
  }

  bool _shouldIgnoreFile(File file) {
    final String path = file.path;
    return _ignoreBasenameList.contains(p.basenameWithoutExtension(path)) ||
        _ignoreSuffixList.any((String suffix) =>
            path.endsWith(suffix) ||
            _ignoredFullBasenameList.contains(p.basename(path)));
  }

  bool _isThirdParty(File file) {
    return path.split(file.path).contains('third_party');
  }

  Future<List<File>> _getAllFiles() => packagesDir.parent
      .list(recursive: true, followLinks: false)
      .where((FileSystemEntity entity) => entity is File)
      .map((FileSystemEntity file) => file as File)
      .toList();

  // Returns the directories containing mapped submodules, if any.
  Future<Iterable<Directory>> _getSubmoduleDirectories() async {
    final List<Directory> submodulePaths = <Directory>[];
    final Directory repoRoot =
        packagesDir.fileSystem.directory((await gitDir).path);
    final File submoduleSpec = repoRoot.childFile('.gitmodules');
    if (submoduleSpec.existsSync()) {
      final RegExp pathLine = RegExp(r'path\s*=\s*(.*)');
      for (final String line in submoduleSpec.readAsLinesSync()) {
        final RegExpMatch? match = pathLine.firstMatch(line);
        if (match != null) {
          submodulePaths.add(repoRoot.childDirectory(match.group(1)!.trim()));
        }
      }
    }
    return submodulePaths;
  }
}

enum _LicenseFailureType { incorrectFirstParty, unknownThirdParty }
