// 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 'dart:convert';
import 'dart:core' hide RegExp;
import 'dart:io' as system;

import 'cache.dart';
import 'formatter.dart';
import 'limits.dart';
import 'patterns.dart';
import 'regexp_debug.dart';

class FetchedContentsOf extends Key { FetchedContentsOf(super.value); }

enum LicenseType {
  afl,
  apache,
  apacheNotice,
  apsl,
  bison,
  bsd,
  eclipse,
  freetype,
  gpl,
  icu,
  defaultTemplate, // metatype: a license that applies to a file without an internal license; only used when searching for a license
  ietf,
  ijg,
  lgpl,
  libpng,
  llvm,
  mit,
  mpl,
  openssl,
  unicode,
  unknown,
  vulkan,
  zlib,
}

LicenseType convertLicenseNameToType(String? name) {
  switch (name) {
    case 'Apache':
    case 'Apache-2.0.txt':
    case 'LICENSE-APACHE-2.0.txt':
    case 'LICENSE.vulkan':
    case 'APACHE-LICENSE-2.0':
      return LicenseType.apache;
    case 'BSD':
    case 'BSD-3-Clause.txt':
    case 'BSD.txt':
      return LicenseType.bsd;
    case 'COPYING-LGPL-2.1':
    case 'LICENSE-LGPL-2':
    case 'LICENSE-LGPL-2.1':
      return LicenseType.lgpl;
    case 'COPYING-GPL-3':
    case 'GPL-3.0-only.txt':
    case 'GPLv2.TXT':
      return LicenseType.gpl;
    case 'FTL.TXT':
      return LicenseType.freetype;
    case 'zlib.h':
      return LicenseType.zlib;
    case 'png.h':
      return LicenseType.libpng;
    case 'ICU':
      return LicenseType.icu;
    case 'Apple Public Source License':
      return LicenseType.apsl;
    case 'OpenSSL':
      return LicenseType.openssl;
    case 'COPYING-MPL-1.1':
    case 'LICENSE.MPLv2':
    case 'http://mozilla.org/MPL/2.0/':
      return LicenseType.mpl;
    case 'COPYRIGHT.vulkan':
      return LicenseType.vulkan;
    case 'LICENSE.MIT':
    case 'MIT':
    case 'MIT.txt':
      return LicenseType.mit;
    // file names that don't say what the type is
    case 'COPYING':
    case 'COPYING.LIB': // lgpl usually
    case 'COPYING.RUNTIME': // gcc exception usually
    case 'COPYING.txt':
    case 'COPYRIGHT.musl':
    case 'Copyright':
    case 'LICENSE':
    case 'LICENSE-APPLE':
    case 'LICENSE.TXT':
    case 'LICENSE.cssmin':
    case 'LICENSE.md':
    case 'LICENSE.rst':
    case 'LICENSE.txt':
    case 'License.txt':
    case 'NOTICE':
    case 'NOTICE.txt':
    case 'copyright':
    case 'extreme.indiana.edu.license.TXT':
    case 'extreme.indiana.edu.license.txt':
    case 'javolution.license.TXT':
    case 'javolution.license.txt':
    case 'libyaml-license.txt':
    case 'license.html':
    case 'license.patch':
    case 'license.txt':
    case 'mh-bsd-gcc':
    case 'pivotal.labs.license.txt':
      return LicenseType.unknown;
  }
  throw 'unknown license type: $name';
}

LicenseType convertBodyToType(String body) {
  if (body.startsWith(lrApache) && body.contains(lrLLVM)) {
    return LicenseType.llvm;
  }
  if (body.startsWith(lrApache)) {
    return LicenseType.apache;
  }
  if (body.startsWith(lrMPL)) {
    return LicenseType.mpl;
  }
  if (body.startsWith(lrGPL)) {
    return LicenseType.gpl;
  }
  if (body.startsWith(lrAPSL)) {
    return LicenseType.apsl;
  }
  if (body.contains(lrOpenSSL)) {
    return LicenseType.openssl;
  }
  if (body.contains(lrBSD)) {
    return LicenseType.bsd;
  }
  if (body.contains(lrMIT)) {
    return LicenseType.mit;
  }
  if (body.contains(lrZlib)) {
    return LicenseType.zlib;
  }
  if (body.contains(lrPNG)) {
    return LicenseType.libpng;
  }
  if (body.contains(lrBison)) {
    return LicenseType.bison;
  }
  return LicenseType.unknown;
}

// API exposed by the classes in main.dart
abstract class LicenseSource {
  String get name;
  String get libraryName;
  String get officialSourceLocation;
  List<License>? nearestLicensesFor(String name);
  License? nearestLicenseOfType(LicenseType type);
  License? nearestLicenseWithName(String name, { String? authors });
}

// Represents a license/file pairing, with metadata saying where the license came from.
class Assignment {
  const Assignment(this.license, this.target, this.source);
  final License license;
  final String target;
  final LicenseSource source;
}

// Represents a group of files assigned to the same license, so that we can avoid
// duplicating licenses in the output.
class GroupedLicense {
  GroupedLicense(this.type, this.body);
  final LicenseType type;
  final String body;

  // The names of files to which this license applies.
  final Set<String> targets = <String>{};

  // The libraries from which those files originate.
  final Set<String> libraries = <String>{};

  // How we determined the license applied to these files.
  final Set<String> origins = <String>{};

  String toStringDebug() {
    final StringBuffer result = StringBuffer();
    result.writeln('=' * 100);
    (libraries.map((String s) => 'LIBRARY: $s').toList()..sort()).forEach(result.writeln);
    (origins.map((String s) => 'ORIGIN: $s').toList()..sort()).forEach(result.writeln);
    result.writeln('TYPE: $type');
    (targets.map((String s) => 'FILE: $s').toList()..sort()).forEach(result.writeln);
    result.writeln('-' * 100);
    if (body.isEmpty) {
      result.writeln('<THIS BLOCK INTENTIONALLY LEFT BLANK>');
    } else {
      result.writeln(body);
    }
    result.writeln('=' * 100);
    return result.toString();
  }

  String toStringFormal() {
    final StringBuffer result = StringBuffer();
    (libraries.toList()..sort()).forEach(result.writeln);
    result.writeln();
    assert(body.isNotEmpty);
    result.write(body);
    return result.toString();
  }
}

List<GroupedLicense> groupLicenses(Iterable<Assignment> assignments) {
  final Map<String, GroupedLicense> groups = <String, GroupedLicense>{};
  for (final Assignment assignment in assignments) {
    final String body = assignment.license.toStringBody(assignment.source);
    final GroupedLicense entry = groups.putIfAbsent(body, () => GroupedLicense(assignment.license.type, body));
    entry.targets.add(assignment.target);
    entry.libraries.add(assignment.source.libraryName);
    entry.origins.add(assignment.license.origin);
  }
  final List<GroupedLicense> results = groups.values.toList();
  results.sort((GroupedLicense a, GroupedLicense b) => a.body.compareTo(b.body));
  return results;
}

abstract class License {
  factory License.unique(String body, LicenseType type, {
    bool reformatted = false,
    required String origin,
    String? authors,
    bool yesWeKnowWhatItLooksLikeButItIsNot = false
  }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final License result = UniqueLicense._(body, type, origin: origin, yesWeKnowWhatItLooksLikeButItIsNot: yesWeKnowWhatItLooksLikeButItIsNot, authors: authors);
    assert(() {
      if (result is! UniqueLicense || result.type != type) {
        throw 'tried to add a UniqueLicense $type, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.template(String body, LicenseType type, {
    bool reformatted = false,
    required String origin,
    String? authors,
  }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final License result = TemplateLicense._autosplit(body, type, origin: origin, authors: authors);
    assert(() {
      if (result is! TemplateLicense || result.type != type) {
        throw 'tried to add a TemplateLicense $type, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.multiLicense(String body, LicenseType type, {
    bool reformatted = false,
    String? authors,
    required String origin
  }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final License result = MultiLicense._(body, type, origin: origin, authors: authors);
    assert(() {
      if (result is! MultiLicense || result.type != type) {
        throw 'tried to add a MultiLicense $type, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.message(String body, LicenseType type, {
    bool reformatted = false,
    required String origin
  }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final License result = MessageLicense._(body, type, origin: origin);
    assert(() {
      if (result is! MessageLicense || result.type != type) {
        throw 'tried to add a MessageLicense $type, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.blank(String body, LicenseType type, { required String origin }) {
    final License result = BlankLicense._(reformat(body), type, origin: origin);
    assert(() {
      if (result is! BlankLicense || result.type != type) {
        throw 'tried to add a BlankLicense $type, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.mozilla(String body, { required String origin }) {
    body = reformat(body);
    final License result = MozillaLicense._(body, LicenseType.mpl, origin: origin);
    assert(() {
      if (result is! MozillaLicense) {
        throw 'tried to add a MozillaLicense, but it was a duplicate of a ${result.runtimeType} ${result.type}';
      }
      return true;
    }());
    return result;
  }

  factory License.fromMultipleBlocks(List<String> bodies, LicenseType type, {
    String? authors,
    required String origin,
    bool yesWeKnowWhatItLooksLikeButItIsNot = false,
  }) {
    final String body = bodies.map((String s) => reformat(s)).join('\n\n');
    return MultiLicense._(body, type, authors: authors, origin: origin, yesWeKnowWhatItLooksLikeButItIsNot: yesWeKnowWhatItLooksLikeButItIsNot);
  }

  factory License.fromBodyAndType(String body, LicenseType type, {
    bool reformatted = false,
    required String origin
  }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final License result;
    assert(type != null);
    switch (type) {
      case LicenseType.bsd:
      case LicenseType.mit:
        result = TemplateLicense._autosplit(body, type, origin: origin);
        break;
      case LicenseType.apache:
      case LicenseType.freetype:
      case LicenseType.ijg:
      case LicenseType.ietf:
      case LicenseType.libpng:
      case LicenseType.llvm: // The LLVM license is an Apache variant
      case LicenseType.unicode:
      case LicenseType.unknown:
      case LicenseType.vulkan:
      case LicenseType.zlib:
        result = MessageLicense._(body, type, origin: origin);
        break;
      case LicenseType.apacheNotice:
        result = UniqueLicense._(body, type, origin: origin);
        break;
      case LicenseType.mpl:
        result = MozillaLicense._(body, type, origin: origin);
        break;
      // The exception in the license of Bison allows redistributing larger
      // works "under terms of your choice"; we choose terms that don't require
      // any notice in the binary distribution.
      case LicenseType.bison:
        result = BlankLicense._(body, type, origin: origin);
        break;
      case LicenseType.icu:
      case LicenseType.openssl:
        throw 'Use License.fromMultipleBlocks rather than License.fromBodyAndType for the ICU and OpenSSL licenses.';
      case LicenseType.afl:
      case LicenseType.apsl:
      case LicenseType.eclipse:
      case LicenseType.gpl:
      case LicenseType.lgpl:
        result = DisallowedLicense._(body, type, origin: origin);
        break;
      case LicenseType.defaultTemplate:
        throw 'should not be creating a LicenseType.defaultTemplate license, it is not a real type';
    }
    assert(result.type == type);
    return result;
  }

  factory License.fromBodyAndName(String body, String name, { required String origin }) {
    body = reformat(body);
    LicenseType type = convertLicenseNameToType(name);
    if (type == LicenseType.unknown) {
      type = convertBodyToType(body);
    }
    return License.fromBodyAndType(body, type, reformatted: true, origin: origin);
  }

  factory License.fromBody(String body, { required String origin, bool reformatted = false }) {
    if (!reformatted) {
      body = reformat(body);
    }
    final LicenseType type = convertBodyToType(body);
    return License.fromBodyAndType(body, type, reformatted: true, origin: origin);
  }

  factory License.fromCopyrightAndLicense(String copyright, String template, LicenseType type, { required String origin }) {
    copyright = reformat(copyright);
    template = reformat(template);
    return TemplateLicense._(copyright, template, type, origin: origin);
  }

  factory License.fromIdentifyingReference(String identifyingReference, { required String referencer }) {
    String body;
    LicenseType type = LicenseType.unknown;
    switch (identifyingReference) {
      case 'Apache-2.0 OR MIT':  // SPDX ID
      case 'Apache-2.0':  // SPDX ID
      case 'Apache:2.0':
      case 'http://www.apache.org/licenses/LICENSE-2.0':
      case 'https://www.apache.org/licenses/LICENSE-2.0':
        // If you're wondering why Abseil has what appears to be a duplicate copy of
        // the Apache license, it's because of this:
        // https://github.com/abseil/abseil-cpp/pull/270/files#r793181143
        body = system.File('data/apache-license-2.0').readAsStringSync();
        type = LicenseType.apache;
        break;
      case 'Apache-2.0 WITH LLVM-exception':  // SPDX ID
      case 'https://llvm.org/LICENSE.txt':
        body = system.File('data/apache-license-2.0-with-llvm-exception').readAsStringSync();
        type = LicenseType.llvm;
        break;
      case 'https://developers.google.com/open-source/licenses/bsd':
        body = system.File('data/google-bsd').readAsStringSync();
        type = LicenseType.bsd;
        break;
      case 'http://polymer.github.io/LICENSE.txt':
        body = system.File('data/polymer-bsd').readAsStringSync();
        type = LicenseType.bsd;
        break;
      case 'http://www.eclipse.org/legal/epl-v10.html':
        body = system.File('data/eclipse-1.0').readAsStringSync();
        type = LicenseType.eclipse;
        break;
      case 'COPYING3:3':
        body = system.File('data/gpl-3.0').readAsStringSync();
        type = LicenseType.gpl;
        break;
      case 'COPYING.LIB:2':
      case 'COPYING.LIother.m_:2': // blame hyatt
        body = system.File('data/library-gpl-2.0').readAsStringSync();
        type = LicenseType.lgpl;
        break;
      case 'GNU Lesser:2':
        // there has never been such a license, but the authors said they meant the LGPL2.1
      case 'GNU Lesser:2.1':
        body = system.File('data/lesser-gpl-2.1').readAsStringSync();
        type = LicenseType.lgpl;
        break;
      case 'COPYING.RUNTIME:3.1':
      case 'GCC Runtime Library Exception:3.1':
        body = system.File('data/gpl-gcc-exception-3.1').readAsStringSync();
        break;
      case 'Academic Free License:3.0':
        body = system.File('data/academic-3.0').readAsStringSync();
        type = LicenseType.afl;
        break;
      case 'Mozilla Public License:1.1':
        body = system.File('data/mozilla-1.1').readAsStringSync();
        type = LicenseType.mpl;
        break;
      case 'http://mozilla.org/MPL/2.0/:2.0':
        body = system.File('data/mozilla-2.0').readAsStringSync();
        type = LicenseType.mpl;
        break;
      case 'MIT':  // SPDX ID
      case 'http://opensource->org/licenses/MIT': // i don't even
      case 'http://opensource.org/licenses/MIT':
      case 'https://opensource.org/licenses/MIT':
        body = system.File('data/mit').readAsStringSync();
        type = LicenseType.mit;
        break;
      case 'Unicode-DFS-2016': // SPDX ID
      case 'http://unicode.org/copyright.html#Exhibit1':
      case 'http://www.unicode.org/copyright.html#License':
      case 'http://www.unicode.org/copyright.html':
      case 'http://www.unicode.org/terms_of_use.html': // redirects to copyright.html
      case 'https://www.unicode.org/copyright.html':
      case 'https://www.unicode.org/terms_of_use.html': // redirects to copyright.html
        body = system.File('data/unicode').readAsStringSync();
        type = LicenseType.unicode;
        break;
      case 'http://www.ietf.org/rfc/rfc3454.txt':
        body = system.File('data/ietf').readAsStringSync();
        type = LicenseType.ietf;
        break;
      default: throw 'unknown identifyingReference $identifyingReference';
    }
    return License.fromBodyAndType(body, type, origin: '$identifyingReference referenced by $referencer');
  }

  License._(String body, this.type, {
    required this.origin,
    String? authors,
    bool yesWeKnowWhatItLooksLikeButItIsNot = false
  }) : authors = authors ?? _readAuthors(body) {
    assert(() {
      try {
        switch (type) {
          case LicenseType.afl:
          case LicenseType.apsl:
          case LicenseType.eclipse:
          case LicenseType.gpl:
          case LicenseType.lgpl:
            // We do not want this kind of license in our build.
            assert(this is DisallowedLicense);
            break;
          case LicenseType.apache:
          case LicenseType.freetype:
          case LicenseType.ijg:
          case LicenseType.ietf:
          case LicenseType.libpng:
          case LicenseType.llvm:
          case LicenseType.unicode:
          case LicenseType.vulkan:
          case LicenseType.zlib:
            assert(this is MessageLicense);
            break;
          case LicenseType.apacheNotice:
            assert(this is UniqueLicense);
            break;
          case LicenseType.bison:
            assert(this is BlankLicense);
            break;
          case LicenseType.bsd:
          case LicenseType.mit:
            assert(this is TemplateLicense);
            break;
          case LicenseType.icu:
          case LicenseType.openssl:
            assert(this is MultiLicense);
            break;
          case LicenseType.mpl:
            assert(this is MozillaLicense);
            break;
          case LicenseType.unknown:
            assert(this is MessageLicense || this is UniqueLicense);
            break;
          case LicenseType.defaultTemplate:
            assert(false, 'should not be creating LicenseType.defaultTemplate license');
            break;
        }
      } on AssertionError {
        throw 'incorrectly created a $runtimeType for a $type';
      }
      return true;
    }());
    final LicenseType detectedType = convertBodyToType(body);
    if (detectedType != LicenseType.unknown && detectedType != type && !yesWeKnowWhatItLooksLikeButItIsNot) {
      throw 'Created a license of type $type but it looks like $detectedType:\n---------\n$body\n-----------';
    }
    if (type != LicenseType.apache && type != LicenseType.llvm && type != LicenseType.vulkan && type != LicenseType.apacheNotice && body.contains('Apache')) {
      throw 'Non-Apache license (type=$type, detectedType=$detectedType) contains the word "Apache"; maybe it\'s a notice?:\n---\n$body\n---';
    }
    if (detectedType != LicenseType.unknown && detectedType != type && !yesWeKnowWhatItLooksLikeButItIsNot) {
      throw 'Created a license of type $type but it looks like $detectedType.';
    }
    if (body.contains(trailingColon)) {
      throw 'incomplete license detected:\n---\n$body\n---';
    }
    bool isUTF8 = true;
    late List<int> latin1Encoded;
    try {
      latin1Encoded = latin1.encode(body);
      isUTF8 = false;
    } on ArgumentError { /* Fall through to next encoding check. */ }
    if (!isUTF8) {
      bool isAscii = false;
      try {
        ascii.decode(latin1Encoded);
        isAscii = true;
      } on FormatException { /* Fall through to next encoding check */ }
      if (isAscii) {
        return;
      }
      try {
        utf8.decode(latin1Encoded);
        isUTF8 = true;
      } on FormatException { /* We check isUTF8 below and throw if necessary */ }
      if (isUTF8) {
        throw 'tried to create a License object with text that appears to have been misdecoded as Latin1 instead of as UTF-8:\n$body';
      }
    }
  }

  final String? authors;
  final String origin;
  final LicenseType type;

  Assignment assignLicenses(String target, LicenseSource source) {
    return Assignment(this, target, source);
  }

  // This takes a second license, which has been pre-split into copyright and
  // licenseBody, and uses this license to expand it into a new license. How
  // this works depends on this license; for example BSD licenses typically take
  // their body and put on the given copyright, (and the licenseBody argument
  // here in those cases is usually a reference to that license); some other
  // licenses turn into two, one for the original license and one for this
  // copyright/body pair.
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin });

  String toStringBody(LicenseSource source);

  static final RegExp _copyrightForAuthors = RegExp(
    r'Copyright [-0-9 ,(cC)©]+\b(The .+ Authors)\.',
    caseSensitive: false
  );

  static String? _readAuthors(String body) {
    final List<Match> matches = _copyrightForAuthors.allMatches(body).toList();
    if (matches.isEmpty) {
      return null;
    }
    if (matches.length > 1) {
      throw 'found too many authors for this copyright:\n$body\n\n${StackTrace.current}\n\n';
    }
    return matches[0].group(1);
  }

  @override
  String toString() => '$runtimeType ($type) from $origin';
}

class _LineRange {
  _LineRange(this.start, this.end, this._body);
  final int start;
  final int end;
  final String _body;
  String? _value;
  String get value {
    _value ??= _body.substring(start, end);
    return _value!;
  }
}

Iterable<_LineRange> _walkLinesBackwards(String body, int start) sync* {
  int? end;
  while (start > 0) {
    start -= 1;
    if (body[start] == '\n') {
      if (end != null) {
        yield _LineRange(start + 1, end, body);
      }
      end = start;
    }
  }
  if (end != null) {
    yield _LineRange(start, end, body);
  }
}

Iterable<_LineRange> _walkLinesForwards(String body, { int start = 0, int? end }) sync* {
  int? startIndex = start == 0 || body[start-1] == '\n' ? start : null;
  int endIndex = startIndex ?? start;
  end ??= body.length;
  while (endIndex < end) {
    if (body[endIndex] == '\n') {
      if (startIndex != null) {
        yield _LineRange(startIndex, endIndex, body);
      }
      startIndex = endIndex + 1;
    }
    endIndex += 1;
  }
  if (startIndex != null) {
    yield _LineRange(startIndex, endIndex, body);
  }
}

class _SplitLicense {
  _SplitLicense(this._body, this._split) : assert(_split == 0 || _split == _body.length || _body[_split] == '\n');

  final String _body;
  final int _split;
  String getCopyright() => _body.substring(0, _split);
  String getConditions() => _split >= _body.length ? '' : _body.substring(_split == 0 ? 0 : _split + 1);
}

_SplitLicense _splitLicense(String body, { bool verifyResults = true }) {
  final Iterator<_LineRange> lines = _walkLinesForwards(body).iterator;
  if (!lines.moveNext()) {
    throw 'tried to split empty license';
  }
  int end = 0;
  String endReason;
  while (true) {
    final String line = lines.current.value;
    if (line == 'Author:' ||
        line == 'This code is derived from software contributed to Berkeley by' ||
        line == 'The Initial Developer of the Original Code is') {
      if (!lines.moveNext()) {
        throw 'unexpected end of block instead of author when looking for copyright';
      }
      if (lines.current.value.trim() == '') {
        throw 'unexpectedly blank line instead of author when looking for copyright';
      }
      end = lines.current.end;
      if (!lines.moveNext()) {
        endReason = 'ran out of text after author';
        break;
      }
    } else if (line.startsWith('Authors:') || line == 'Other contributors:') {
      if (line != 'Authors:') {
        // assume this line contained an author as well
        end = lines.current.end;
      }
      if (!lines.moveNext()) {
        throw 'unexpected end of license when reading list of authors while looking for copyright';
      }
      final String firstAuthor = lines.current.value;
      int subindex = 0;
      while (subindex < firstAuthor.length && (firstAuthor[subindex] == ' ')) {
        subindex += 1;
      }
      if (subindex == 0 || subindex > firstAuthor.length) {
        throw 'unexpected blank line instead of authors found when looking for copyright';
      }
      end = lines.current.end;
      final String prefix = firstAuthor.substring(0, subindex);
      bool hadMoreLines;
      while ((hadMoreLines = lines.moveNext()) && lines.current.value.startsWith(prefix)) {
        final String nextAuthor = lines.current.value.substring(prefix.length);
        if (nextAuthor == '' || nextAuthor[0] == ' ') {
          throw 'unexpectedly ragged author list when looking for copyright';
        }
        end = lines.current.end;
      }
      if (!hadMoreLines) {
        endReason = 'ran out of text while collecting authors';
        break;
      }
    } else if (line.contains(halfCopyrightPattern)) {
      do {
        if (!lines.moveNext()) {
          throw 'unexpected end of block instead of copyright holder when looking for copyright';
        }
        if (lines.current.value.trim() == '') {
          throw 'unexpectedly blank line instead of copyright holder when looking for copyright';
        }
        end = lines.current.end;
      } while (lines.current.value.contains(trailingComma));
      if (!lines.moveNext()) {
        endReason = 'ran out of text after matching halfCopyrightPattern/trailingComma sequence';
        break;
      }
    } else if (copyrightStatementPatterns.any(line.contains)) {
      end = lines.current.end;
      if (!lines.moveNext()) {
        endReason = 'ran out of text after copyright statement pattern';
        break;
      }
    } else {
      endReason = 'line did not match any copyright patterns ("$line")';
      break;
    }
  }
  if (verifyResults && 'Copyright ('.allMatches(body, end).isNotEmpty && !body.startsWith('If you modify libpng')) {
    throw 'the license seems to contain a copyright:\n===copyright===\n${body.substring(0, end)}\n===license===\n${body.substring(end)}\n=========\ntermination reason: $endReason';
  }
  return _SplitLicense(body, end);
}

class _PartialLicenseMatch {
  _PartialLicenseMatch(this._body, this.start, this.split, this.end, this._match, { required this.hasCopyrights }) : assert(split >= start),
          assert(split == start || _body[split] == '\n');

  final String _body;
  final int start;
  final int split;
  final int end;
  final Match _match;
  String? group(int? index) => _match.group(index!);
  String? getAuthors() {
    final Match? match = authorPattern.firstMatch(getCopyrights());
    if (match != null) {
      return match.group(1);
    }
    return null;
  }
  String getCopyrights() => _body.substring(start, split);
  String getConditions() => _body.substring(split + 1, end);
  String getEntireLicense() => _body.substring(start, end);
  final bool hasCopyrights;
}

// Look for all matches of `pattern` in `body` and return them along with associated copyrights.
Iterable<_PartialLicenseMatch> _findLicenseBlocks(String body, RegExp pattern, int firstPrefixIndex, int indentPrefixIndex, { bool needsCopyright = true }) sync* {
  // I tried doing this with one big RegExp initially, but that way lay madness.
  for (final Match match in pattern.allMatches(body)) {
    assert(match.groupCount >= firstPrefixIndex);
    assert(match.groupCount >= indentPrefixIndex);
    int start = match.start;
    final String fullPrefix = '${match.group(firstPrefixIndex)}${match.group(indentPrefixIndex)}';
    // first we walk back to the start of the block that has the same prefix (e.g.
    // the start of this comment block)
    int firstLineOffset = 0;
    bool lastWasBlank = false;
    bool foundNonBlank = false;
    for (final _LineRange range in _walkLinesBackwards(body, start)) {
      String line = range.value;
      bool isBlockCommentLine;
      if (line.length > 3 && line.endsWith('*/')) {
        int index = line.length - 3;
        while (line[index] == ' ') {
          index -= 1;
        }
        line = line.substring(0, index + 1);
        isBlockCommentLine = true;
      } else {
        isBlockCommentLine = false;
      }
      if (line.isEmpty || fullPrefix.startsWith(line)) {
        // this is a blank line
        if (lastWasBlank && (foundNonBlank || !needsCopyright)) {
          break;
        }
        lastWasBlank = true;
      } else if (!isBlockCommentLine && line.startsWith('/*')) {
        start = range.start;
        firstLineOffset = 2;
        break;
      } else if (line.startsWith('<!--')) {
        start = range.start;
        firstLineOffset = 4;
        break;
      } else if (fullPrefix.isNotEmpty && !line.startsWith(fullPrefix)) {
        break;
      } else if (licenseFragments.any((RegExp pattern) => line.contains(pattern))) {
        // we're running into another license, abort, abort!
        break;
      } else {
        lastWasBlank = false;
        foundNonBlank = true;
      }
      start = range.start;
    }
    // then we walk forward dropping anything until the first line that matches what
    // we think might be part of a copyright statement
    bool foundAny = false;
    RegExp? debugFirstPattern;
    copyrightSearch: for (final _LineRange range in _walkLinesForwards(body, start: start, end: match.start)) {
      String line = range.value;
      if (firstLineOffset > 0) {
        line = line.substring(firstLineOffset);
        firstLineOffset = 0;
      } else if (line.startsWith(fullPrefix)) {
        line = line.substring(fullPrefix.length);
      } else {
        assert(line.isEmpty || fullPrefix.startsWith(line), 'invariant violated: expected this to be a blank line but it was "$line" (prefix is "$fullPrefix").');
        continue copyrightSearch;
      }
      for (final RegExp pattern in copyrightStatementLeadingPatterns) {
        if (line.contains(pattern)) {
          start = range.start;
          foundAny = true;
          debugFirstPattern = pattern;
          break copyrightSearch;
        }
      }
    }
    // At this point we have figured out what might be copyright text before the license (if anything).
    int split;
    if (!foundAny) {
      if (needsCopyright) {
       throw 'could not find copyright before license\nlicense body was:\n---\n${body.substring(match.start, match.end)}\n---\nfile was:\n---\n$body\n---';
      }
      start = match.start;
      split = match.start;
    } else {
      final String copyrights = body.substring(start, match.start);
      final String undecoratedCopyrights = reformat(copyrights);
      // Let's try splitting the copyright block as if it was a license.
      // This will tell us if we collected something in the copyright block
      // that was more license than copyright and that therefore should be
      // examined closer.
      final _SplitLicense consistencyCheck = _splitLicense(undecoratedCopyrights, verifyResults: false);
      final String conditions = consistencyCheck.getConditions();
      if (conditions != '') {
        // Copyright lines long enough to spill to a second line can create
        // false positives; try to weed those out.
        final String resplitCopyright = consistencyCheck.getCopyright();
        if (resplitCopyright.trim().contains('\n') ||
            conditions.trim().contains('\n') ||
            resplitCopyright.length < 70 ||
            conditions.length > 15) {
          throw 'potential license text caught in _findLicenseBlocks copyright dragnet:\n---\n$conditions\n---\nundecorated copyrights was:\n---\n$undecoratedCopyrights\n---\ncopyrights was:\n---\n$copyrights\n---\nblock was:\n---\n${body.substring(start, match.end)}\n---\nfirst line matched: $debugFirstPattern\n---\npattern:\n$pattern\n---\n${StackTrace.current}\n=============';
        }
      }

      if (!copyrights.contains(anySlightSignOfCopyrights)) {
        throw 'could not find copyright before license block:\n---\ncopyrights was:\n---\n$copyrights\n---\nblock was:\n---\n${body.substring(start, match.end)}\n---';
      }
      assert(body[match.start - 1] == '\n', 'match did not start at a newline; match.start = ${match.start}, match.end = ${match.end}, split at: "${body[match.start - 1]}"');
      split = match.start - 1;
    }
    yield _PartialLicenseMatch(body, start, split, match.end, match, hasCopyrights: foundAny);
  }
}

class _LicenseMatch {
  _LicenseMatch(this.license, this.start, this.end, {
    this.debug = '',
    this.ignoreWhenCheckingOverlappingRegions = false,
    this.missingCopyrights = false
  });
  final License license;
  final int start;
  final int end;
  final String debug;
  final bool ignoreWhenCheckingOverlappingRegions;
  final bool missingCopyrights;

  @override
  String toString() {
    return '$start..$end: $license';
  }
}

Iterable<_LicenseMatch> _expand(License template, String copyright, String body, int start, int end, { String debug = '', required String origin }) sync* {
  final List<License> results = template._expandTemplate(reformat(copyright), body, origin: origin).toList();
  if (results.isEmpty) {
    throw 'license could not be expanded';
  }
  yield _LicenseMatch(results.first, start, end, debug: 'expanding template for $debug');
  if (results.length > 1) {
    yield* results.skip(1).map((License license) => _LicenseMatch(license, start, end, ignoreWhenCheckingOverlappingRegions: true, debug: 'expanding subsequent template for $debug'));
  }
}

Iterable<_LicenseMatch> _tryReferenceByFilename(String body, LicenseFileReferencePattern pattern, LicenseSource parentDirectory, { required String origin }) sync* {
  if (pattern.copyrightIndex != null) {
    for (final Match match in pattern.pattern.allMatches(body)) {
      final String copyright = match.group(pattern.copyrightIndex!)!;
      final String? authors = pattern.authorIndex != null ? match.group(pattern.authorIndex!) : null;
      final String filename = match.group(pattern.fileIndex)!;
      final License? template = parentDirectory.nearestLicenseWithName(filename, authors: authors);
      if (template == null) {
        throw 'failed to find template $filename in $parentDirectory (authors=$authors)';
      }
      assert(reformat(copyright) != '');
      final String entireLicense = body.substring(match.start, match.end);
      yield* _expand(template, copyright, entireLicense, match.start, match.end, debug: '_tryReferenceByFilename (with explicit copyright) looking for $filename', origin: origin);
    }
  } else {
    for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex, needsCopyright: pattern.needsCopyright)) {
      final String? authors = match.getAuthors();
      String? filename = match.group(pattern.fileIndex);
      if (filename == 'modp_b64.c') {
        filename = 'modp_b64.cc'; // it was renamed but other files reference the old name
      }
      // There's also special cases for fuchsia/sdk/linux/dart/zircon/lib/src/fakes/handle_disposition.dart
      // (which points to "The Flutter Authors" instead of "The Fuchsia Authors" for mysterious reasons) and
      // third_party/angle/src/common/fuchsia_egl/fuchsia_egl.* (which does something similar), but those
      // files never reach here because they're marked as binary files in filesystem.dart.
      final License? template = parentDirectory.nearestLicenseWithName(filename!, authors: authors);
      if (template == null) {
        throw
          'failed to find accompanying "$filename" in $parentDirectory\n'
          'block:\n---\n${match.getEntireLicense()}\n---';
      }
      if (match.getCopyrights() == '') {
        yield _LicenseMatch(template, match.start, match.end, debug: '_tryReferenceByFilename (with failed copyright search) looking for $filename');
      } else {
        yield* _expand(template, match.getCopyrights(), match.getEntireLicense(), match.start, match.end, debug: '_tryReferenceByFilename (with successful copyright search) looking for $filename', origin: origin);
      }
    }
  }
}

Iterable<_LicenseMatch> _tryReferenceByType(String body, RegExp pattern, LicenseSource parentDirectory, { required String origin }) sync* {
  for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: false)) {
    final LicenseType type = convertLicenseNameToType(match.group(3));
    final License? template = parentDirectory.nearestLicenseOfType(type);
    if (template == null) {
      throw 'failed to find accompanying $type license in $parentDirectory';
    }
    if (match.getCopyrights() == '') {
      yield _LicenseMatch(template, match.start, match.end, debug: '_tryReferenceByType (without copyrights) for type $type');
    } else {
      yield* _expand(template, match.getCopyrights(), match.getEntireLicense(), match.start, match.end, debug: '_tryReferenceByType (with successful copyright search) for type $type', origin: origin);
    }
  }
}

License _dereferenceLicense(int groupIndex, String? Function(int index) group, LicenseReferencePattern pattern, LicenseSource parentDirectory, { required String origin }) {
  License? result = pattern.checkLocalFirst ? parentDirectory.nearestLicenseWithName(group(groupIndex)!) : null;
  result ??= License.fromIdentifyingReference(group(groupIndex)!, referencer: origin);
  return result;
}

Iterable<_LicenseMatch> _tryReferenceByIdentifyingReference(String body, LicenseReferencePattern pattern, LicenseSource parentDirectory, { required String origin }) sync* {
  for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern.pattern!, 1, 2, needsCopyright: false)) {
    if (pattern.spdx) {
      // Per legal advice, we allowlist the use of SPDX headers. Currently, we
      // recognize SPDX headers in code from Khronos. To identify such code, we
      // examine the copyright that came with the SPDX header or we look at the
      // library name. We also accept the headers in some libcxx files that have
      // their own license and that otherwise would trip up our code checking
      // for missed licenses and copyrights. To identify those, we use the
      // library name and the parent directory name or copyright.
      bool allowSpdx = false;
      final String copyrights = match.getCopyrights();
      if (copyrights.contains('The Khronos Group') ||
          parentDirectory.libraryName == 'spirv-cross' ||
          (parentDirectory.libraryName == 'libcxx' && parentDirectory.name == 'ryu') ||
          (parentDirectory.libraryName == 'libcxx' && copyrights.contains('Microsoft'))) {
        allowSpdx = true;
      }
      if (!allowSpdx) {
        // Skip this match.
        continue;
      }
    }
    assert(match.group(3) != null, 'pattern ${pattern.pattern!} did not have three groups when matched against:\n---\n$body\n---\nmatch: $match');
    final License template = _dereferenceLicense(3, match.group, pattern, parentDirectory, origin: origin);
    if (match.getCopyrights() == '') {
      yield _LicenseMatch(template, match.start, match.end, debug: '_tryReferenceByIdentifyingReference (without copyrights)');
    } else {
      yield* _expand(template, match.getCopyrights(), match.getEntireLicense(), match.start, match.end, debug: '_tryReferenceByIdentifyingReference (with copyright)', origin: origin);
    }
  }
}

Iterable<_LicenseMatch> _tryInline(String body, RegExp pattern, {
  required bool needsCopyright,
  required String origin,
}) sync* {
  assert(needsCopyright != null);
  for (final _PartialLicenseMatch match in _findLicenseBlocks(body, pattern, 1, 2, needsCopyright: needsCopyright)) {
    yield _LicenseMatch(License.fromBody(match.getEntireLicense(), origin: origin), match.start, match.end, debug: '_tryInline', missingCopyrights: needsCopyright && !match.hasCopyrights);
  }
}

Iterable<_LicenseMatch> _tryStray(String body, RegExp pattern, LicenseSource parentDirectory, { required String origin }) sync* {
  // this one doesn't look for copyrights (that's the point, the patterns _are_ the copyrights)
  bool gotTemplate = false;
  License? template;
  for (final Match match in pattern.allMatches(body)) {
    if (!gotTemplate) {
      template = parentDirectory.nearestLicenseOfType(LicenseType.defaultTemplate);
      gotTemplate = true;
    }
    if (template != null) {
      yield* _expand(template, match.group(0)!, match.group(0)!, match.start, match.end, debug: '_tryStray (with template)', origin: origin);
    } else {
      yield _LicenseMatch(License.fromBody(match.group(0)!, origin: origin), match.start, match.end, debug: '_tryStray');
    }
  }
}

Iterable<_LicenseMatch> _tryForwardReferencePattern(String fileContents, ForwardReferencePattern pattern, License template, LicenseSource source, { required String origin }) sync* {
  String? body;
  for (final _PartialLicenseMatch match in _findLicenseBlocks(fileContents, pattern.pattern, pattern.firstPrefixIndex, pattern.indentPrefixIndex)) {
    body ??= template.toStringBody(source);
    if (!body.contains(pattern.targetPattern)) {
      throw
        'forward license reference to unexpected license\n'
        'license:\n---\n$body\n---\nexpected pattern:\n---\n${pattern.targetPattern}\n---';
    }
    yield* _expand(template, match.getCopyrights(), match.getEntireLicense(), match.start, match.end, debug: '_tryForwardReferencePattern', origin: origin);
  }
}

List<License> determineLicensesFor(String fileContents, String filename, LicenseSource? parentDirectory, { required String origin }) {
  if (parentDirectory == null) {
    throw 'Fatal error: determineLicensesFor was called with parentDirectory=null!';
  }
  if (fileContents.length > kMaxSize) {
    fileContents = fileContents.substring(0, kMaxSize);
  }
  final List<_LicenseMatch> results = <_LicenseMatch>[];
  fileContents = stripAsciiArt(fileContents);
  results.addAll(csReferencesByFilename.expand((LicenseFileReferencePattern pattern) => _tryReferenceByFilename(fileContents, pattern, parentDirectory, origin: origin)));
  results.addAll(csReferencesByType.expand((RegExp pattern) => _tryReferenceByType(fileContents, pattern, parentDirectory, origin: origin)));
  results.addAll(csReferencesByIdentifyingReference.expand((LicenseReferencePattern pattern) => _tryReferenceByIdentifyingReference(fileContents, pattern, parentDirectory, origin: origin)));
  results.addAll(csTemplateLicenses.expand((RegExp pattern) => _tryInline(fileContents, pattern, needsCopyright: true, origin: origin)));
  results.addAll(csNoticeLicenses.expand((RegExp pattern) => _tryInline(fileContents, pattern, needsCopyright: false, origin: origin)));
  _LicenseMatch? usedTemplate;
  if (results.length == 1) {
    final _LicenseMatch target = results.single;
    results.addAll(csForwardReferenceLicenses.expand((ForwardReferencePattern pattern) => _tryForwardReferencePattern(fileContents, pattern, target.license, parentDirectory, origin: origin)));
    if (results.length > 1) {
      usedTemplate = target;
    }
  }
  for (final _LicenseMatch match in results.where((_LicenseMatch match) => match.missingCopyrights)) {
    throw 'found a license for $filename but could not match its copyright:\n----8<----\n${match.license}\n----8<----';
  }
  if (results.isEmpty) {
    if ((fileContents.contains(copyrightMentionPattern) && fileContents.contains(licenseMentionPattern)) && !fileContents.contains(copyrightMentionOkPattern)) {
      throw 'failed to find any license but saw unmatched potential copyright and license statements; first twenty lines:\n----8<----\n${fileContents.split("\n").take(20).join("\n")}\n----8<----';
    }
  }
  // Some files have the odd copyright that isn't explicitly attached to a
  // license; we treat those as notice licenses. Only such copyrights
  // allowlisted in csStrayCopyrights are handled this way, though. For each of
  // these, we have to make sure they don't overlap any of the actual licenses
  // matched earlier, so we check for overlaps on each one first.
  strays: for (final _LicenseMatch stray in csStrayCopyrights.expand((RegExp pattern) => _tryStray(fileContents, pattern, parentDirectory, origin: origin))) {
    for (final _LicenseMatch full in results) {
      if (stray.start >= full.start && stray.end <= full.end) {
        continue strays;
      }
    }
    results.add(stray);
  }
  final List<_LicenseMatch> verificationList = results.toList();
  if (usedTemplate != null && !verificationList.contains(usedTemplate)) {
    verificationList.add(usedTemplate);
  }
  verificationList.sort((_LicenseMatch a, _LicenseMatch b) {
    final int result = a.start - b.start;
    if (result != 0) {
      return result;
    }
    return a.end - b.end;
  });
  int position = 0;
  for (final _LicenseMatch m in verificationList) {
    if (m.ignoreWhenCheckingOverlappingRegions) {
      continue;
    } // some text expanded into multiple licenses, so overlapping is expected
    if (position > m.start) {
      system.stderr.writeln('\n\noverlapping licenses:');
      for (final _LicenseMatch n in results) {
        system.stderr.writeln(
          'license match: ${n.start}..${n.end}, ${n.license.runtimeType}, ${n.debug}\n'
          '  first line: ${n.license.toStringBody(parentDirectory).split("\n").first}\n'
          '  last line: ${n.license.toStringBody(parentDirectory).split("\n").last}'
        );
      }
      throw 'overlapping licenses in $filename (one ends at $position, another starts at ${m.start})';
    }
    if (position < m.start) {
      final String substring = fileContents.substring(position, m.start);
      if (substring.contains(copyrightMentionPattern) && !substring.contains(copyrightMentionOkPattern)) {
        throw 'there is another unmatched potential copyright statement in $filename:\n  $position..${m.start}: "$substring"\nmatched licenses: $results';
      }
      if (substring.contains(licenseMentionPattern)) {
        throw 'there is another unmatched potential license in $filename:\n  $position..${m.start}: "$substring"\nmatched licenses: $results';
      }
    }
    position = m.end;
  }
  final String substring = fileContents.substring(position);
  if (substring.contains(copyrightMentionPattern) && !substring.contains(copyrightMentionOkPattern)) {
    throw 'there is an unmatched potential copyright statement in $filename:\n  $position..end: "$substring"\nmatched licenses: $results';
  }
  if (substring.contains(licenseMentionPattern)) {
    throw 'there is an unmatched potential license in $filename:\n  $position..end: "$substring"\nmatched licenses: $results';
  }
  return results.map((_LicenseMatch entry) => entry.license).toSet().toList();
}

License? interpretAsRedirectLicense(String fileContents, LicenseSource parentDirectory, { required String origin }) {
  _SplitLicense split;
  try {
    split = _splitLicense(fileContents);
  } on String {
    return null;
  }
  final String body = split.getConditions().trim();
  License? result;
  for (final LicenseReferencePattern pattern in csReferencesByIdentifyingReference) {
    if (pattern.spdx) {
      // We don't support SPDX headers in files that use _RepositoryLicenseRedirectFile.
      // Before changing this, obtain legal advice.
      continue;
    }
    final Match? match = pattern.pattern!.matchAsPrefix(body);
    if (match != null && match.start == 0 && match.end == body.length) {
      final License candidate = _dereferenceLicense(3, match.group as String? Function(int?), pattern, parentDirectory, origin: origin);
      if (result != null && candidate != null) {
        throw 'Multiple potential matches in interpretAsRedirectLicense in $parentDirectory; body was:\n------8<------\n$fileContents\n------8<------';
      }
      result = candidate;
    }
  }
  return result;
}

// the kind of license that just wants to show a message (e.g. the JPEG one)
class MessageLicense extends License {
  MessageLicense._(this.body, LicenseType type, { required String origin }) : super._(body, type, origin: origin);

  final String body;

  @override
  String toStringBody(LicenseSource source) => body;

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) => <License>[this];
}

// the kind of license that says to include the copyright and the license text (e.g. BSD)
class TemplateLicense extends License {
  TemplateLicense._(this.defaultCopyright, this.terms, LicenseType type, { String? authors, required String origin })
    : assert(!defaultCopyright.endsWith('\n')),
      assert(!terms.startsWith('\n')),
      assert(terms.isNotEmpty),
      super._('$defaultCopyright\n\n$terms', type, origin: origin, authors: authors);

  factory TemplateLicense._autosplit(String body, LicenseType type, { String? authors, required String origin }) {
    final _SplitLicense bits = _splitLicense(body);
    final String copyright = bits.getCopyright();
    final String terms = bits.getConditions();
    assert((copyright.isEmpty && terms == body) || ('$copyright\n$terms' == body) || (copyright == body && terms.isEmpty), '_splitLicense contract violation.\nCOPYRIGHT:\n===\n$copyright\n===\nTERMS:\n===\n$terms\n===\nBODY:\n===\n$body\n===\n');
    int copyrightLength = copyright.length;
    while (copyrightLength > 0 && copyright[copyrightLength - 1] == '\n') {
      copyrightLength -= 1;
    }
    int termsStart = 0;
    while (termsStart < terms.length && terms[termsStart] == '\n') {
      termsStart += 1;
    }
    return TemplateLicense._(
      copyright.substring(0, copyrightLength),
      terms.substring(termsStart),
      type,
      authors: authors,
      origin: origin,
    );
  }

  final String defaultCopyright;
  final String terms;

  @override
  String toStringBody(LicenseSource source) {
    if (defaultCopyright.isEmpty) {
      return terms;
    }
    return '$defaultCopyright\n\n$terms';
  }

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    return <License>[ License.fromCopyrightAndLicense(copyright, terms, type, origin: '$origin + ${this.origin}') ];
  }
}

// The kind of license that expands to two license blocks a main license and the referring block
// (e.g. OpenSSL).
//
// This is a lawyer-suggested workaround for handling BSD-style licenses where instead of there
// being a single license block where it's obvious what is meant by "above copyright notice" and
// "this list of conditions", we instead have a bunch of similar licenses, each with their own
// copyright, plus there's a copyright in the file that (probably) doesn't exactly match any of the
// copyrights in the file, plus some text saying that that license applies to the file.
class MultiLicense extends License {
  MultiLicense._(this.body, LicenseType type, {
    String? authors,
    required String origin,
    bool yesWeKnowWhatItLooksLikeButItIsNot = false,
  }) : super._(body, type, origin: origin, authors: authors, yesWeKnowWhatItLooksLikeButItIsNot: yesWeKnowWhatItLooksLikeButItIsNot);

  final String body;

  @override
  String toStringBody(LicenseSource source) => body;

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    // Sometimes a license (e.g. the OpenSSL license in the BoringSSL package) is referenced
    // from a file that has its own copyright header. When that happens we just print the referenced
    // license and the reference to that license separately because it's not at all clear how we're
    // supposed to merge them otherwise.
    licenseBody = reformat(licenseBody);
    assert(licenseBody.startsWith(copyright), 'copyright:\n---\n$copyright\n---\nlicenseBody:\n---\n$licenseBody\n---');
    return <License>[
      this,
      License.fromBody(licenseBody, origin: '$origin (with ${this.origin})', reformatted: true),
    ];
  }
}

// the kind of license that should not be combined with separate copyright notices
class UniqueLicense extends License {
  UniqueLicense._(this.body, LicenseType type, {
    required String origin,
    String? authors,
    bool yesWeKnowWhatItLooksLikeButItIsNot = false
  }) : super._(body, type, origin: origin, yesWeKnowWhatItLooksLikeButItIsNot: yesWeKnowWhatItLooksLikeButItIsNot, authors: authors);

  final String body;

  @override
  String toStringBody(LicenseSource source) => body;

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    throw 'attempted to expand non-template license with "$copyright"\ntemplate was: $this';
  }
}

// the kind of license that doesn't need to be reported anywhere
class BlankLicense extends License {
  BlankLicense._(super.body, super.type, { required super.origin }) : super._();

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    // We don't care what copyrights this kind of license has, we don't need
    // to report them. Just report |this| (which is always blank, see below).
    return <License>[this];
  }

  @override
  String toStringBody(LicenseSource source) => '';
}

// MPL
class MozillaLicense extends License {
  MozillaLicense._(this.body, LicenseType type, { required String origin }) : assert(type == LicenseType.mpl), super._(body, type, origin: origin);

  final String body;

  @override
  Assignment assignLicenses(String target, LicenseSource source) {
    if (source.libraryName != 'root_certificates') {
      throw 'Only root_certificates is allowed to use the MPL.';
    }
    return Assignment(this, target, source);
  }

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    throw 'attempted to expand non-template license with "$copyright"\ntemplate was: $this';
  }

  @override
  String toStringBody(LicenseSource source) {
    final StringBuffer result = StringBuffer();
    result.writeln(body);
    result.writeln();
    result.writeln("You may obtain a copy of this library's Source Code Form from: ${source.officialSourceLocation}");
    return result.toString();
  }
}

class DisallowedLicense extends License {
  DisallowedLicense._(this.body, LicenseType type, { required String origin }) : super._(body, type, origin: origin);

  final String body;

  @override
  Assignment assignLicenses(String target, LicenseSource source) {
    throw '$target (in ${source.libraryName}) attempted to use $origin which is a disallowed license type ($type)';
  }

  @override
  Iterable<License> _expandTemplate(String copyright, String licenseBody, { required String origin }) {
    throw 'attempted to use $origin which is a disallowed license type ($type)';
  }

  @override
  String toStringBody(LicenseSource source) {
    throw '${source.libraryName} attempted to use $origin which is a disallowed license type ($type)';
  }
}
