// 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:xml/xml.dart';
import 'package:yaml/yaml.dart';

import '../base/deferred_component.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../build_system/build_system.dart';
import 'deferred_components_validator.dart';

/// A class to configure and run deferred component setup verification checks
/// and tasks.
///
/// Once constructed, checks and tasks can be executed by calling the respective
/// methods. The results of the checks are stored internally and can be
/// displayed to the user by calling [displayResults].
class DeferredComponentsGenSnapshotValidator extends DeferredComponentsValidator {
  /// Constructs a validator instance.
  ///
  /// The [env] property is used to locate the project files that are checked.
  ///
  /// The [templatesDir] parameter is optional. If null, the tool's default
  /// templates directory will be used.
  ///
  /// When [exitOnFail] is set to true, the [handleResults] and [attemptToolExit]
  /// methods will exit the tool when this validator detects a recommended
  /// change. This defaults to true.
  DeferredComponentsGenSnapshotValidator(this.env, {
    bool exitOnFail = true,
    String? title,
  }) : super(env.projectDir, env.logger, env.platform, exitOnFail: exitOnFail, title: title);

  /// The build environment that should be used to find the input files to run
  /// checks against.
  ///
  /// The checks in this class are meant to be used as part of a build process,
  /// so an environment should be available.
  final Environment env;

  // The key used to identify the metadata element as the loading unit id to
  // deferred component mapping.
  static const String _mappingKey = 'io.flutter.embedding.engine.deferredcomponents.DeferredComponentManager.loadingUnitMapping';

  /// Checks if the base module `app`'s `AndroidManifest.xml` contains the
  /// required meta-data that maps loading units to deferred components.
  ///
  /// Returns true if the check passed with no recommended changes, and false
  /// otherwise.
  ///
  /// Flutter engine uses a manifest meta-data mapping to determine which
  /// deferred component includes a particular loading unit id. This method
  /// checks if `app`'s `AndroidManifest.xml` contains this metadata. If not, it
  /// will generate a modified AndroidManifest.xml with the correct metadata
  /// entry.
  ///
  /// An example mapping:
  ///
  ///   2:componentA,3:componentB,4:componentC
  ///
  /// Where loading unit 2 is included in componentA, loading unit 3 is included
  /// in componentB, and loading unit 4 is included in componentC.
  bool checkAppAndroidManifestComponentLoadingUnitMapping(List<DeferredComponent> components, List<LoadingUnit> generatedLoadingUnits) {
    final Directory androidDir = projectDir.childDirectory('android');
    inputs.add(projectDir.childFile('pubspec.yaml'));

    // We do not use the Xml package to handle the writing, as we do not want to
    // erase any user applied formatting and comments. The changes can be
    // applied with dart io and custom parsing.
    final File appManifestFile = androidDir
      .childDirectory('app')
      .childDirectory('src')
      .childDirectory('main')
      .childFile('AndroidManifest.xml');
    inputs.add(appManifestFile);
    if (!appManifestFile.existsSync()) {
      invalidFiles[appManifestFile.path] = 'Error: $appManifestFile does not '
        'exist or could not be found. Please ensure an AndroidManifest.xml '
        "exists for the app's base module.";
      return false;
    }
    XmlDocument document;
    try {
      document = XmlDocument.parse(appManifestFile.readAsStringSync());
    } on XmlParserException {
      invalidFiles[appManifestFile.path] = 'Error parsing $appManifestFile '
        'Please ensure that the android manifest is a valid XML document and '
        'try again.';
      return false;
    } on FileSystemException {
      invalidFiles[appManifestFile.path] = 'Error reading $appManifestFile '
        'even though it exists. Please ensure that you have read permission for '
        'this file and try again.';
      return false;
    }
    // Create loading unit mapping.
    final Map<int, String> mapping = <int, String>{};
    for (final DeferredComponent component in components) {
      component.assignLoadingUnits(generatedLoadingUnits);
      final Set<LoadingUnit>? loadingUnits = component.loadingUnits;
      if (loadingUnits == null) {
        continue;
      }
      for (final LoadingUnit unit in loadingUnits) {
        if (!mapping.containsKey(unit.id)) {
          mapping[unit.id] = component.name;
        }
      }
    }
    for (final LoadingUnit unit in generatedLoadingUnits) {
      if (!mapping.containsKey(unit.id)) {
        // Store an empty string for unassigned loading units,
        // indicating that it is in the base component.
        mapping[unit.id] = '';
      }
    }
    // Encode the mapping as a string.
    final StringBuffer mappingBuffer = StringBuffer();
    for (final int key in mapping.keys) {
      mappingBuffer.write('$key:${mapping[key]},');
    }
    String encodedMapping = mappingBuffer.toString();
    // remove trailing comma if any
    if (encodedMapping.endsWith(',')) {
      encodedMapping = encodedMapping.substring(0, encodedMapping.length - 1);
    }
    // Check for existing metadata entry and see if needs changes.
    bool exists = false;
    bool modified = false;
    for (final XmlElement application in document.findAllElements('application')) {
      for (final XmlElement metaData in application.findElements('meta-data')) {
        final String? name = metaData.getAttribute('android:name');
        if (name == _mappingKey) {
          exists = true;
          final String? storedMappingString = metaData.getAttribute('android:value');
          if (storedMappingString != encodedMapping) {
            metaData.setAttribute('android:value', encodedMapping);
            modified = true;
          }
        }
      }
    }
    if (!exists) {
      // Create an meta-data XmlElement that contains the mapping.
      final XmlElement mappingMetadataElement = XmlElement(XmlName.fromString('meta-data'),
        <XmlAttribute>[
          XmlAttribute(XmlName.fromString('android:name'), _mappingKey),
          XmlAttribute(XmlName.fromString('android:value'), encodedMapping),
        ],
      );
      for (final XmlElement application in document.findAllElements('application')) {
        application.children.add(mappingMetadataElement);
        break;
      }
    }
    if (!exists || modified) {
      final File manifestOutput = outputDir
        .childDirectory('app')
        .childDirectory('src')
        .childDirectory('main')
        .childFile('AndroidManifest.xml');
      ErrorHandlingFileSystem.deleteIfExists(manifestOutput);
      manifestOutput.createSync(recursive: true);
      manifestOutput.writeAsStringSync(document.toXmlString(pretty: true), flush: true);
      modifiedFiles.add(manifestOutput.path);
      return false;
    }
    return true;
  }

  /// Compares the provided loading units against the contents of the
  /// `deferred_components_loading_units.yaml` file.
  ///
  /// Returns true if a loading unit cache file exists and all loading units
  /// match, and false otherwise.
  ///
  /// This method will parse the cached loading units file if it exists and
  /// compare it to the provided generatedLoadingUnits. It will distinguish
  /// between newly added loading units and no longer existing loading units. If
  /// the cache file does not exist, then all generatedLoadingUnits will be
  /// considered new.
  bool checkAgainstLoadingUnitsCache(
      List<LoadingUnit> generatedLoadingUnits) {
    final List<LoadingUnit> cachedLoadingUnits = _parseLoadingUnitsCache(projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName));
    loadingUnitComparisonResults = <String, Object>{};
    final Set<LoadingUnit> unmatchedLoadingUnits = <LoadingUnit>{};
    final List<LoadingUnit> newLoadingUnits = <LoadingUnit>[];
    if (generatedLoadingUnits == null || cachedLoadingUnits == null) {
      loadingUnitComparisonResults!['new'] = newLoadingUnits;
      loadingUnitComparisonResults!['missing'] = unmatchedLoadingUnits;
      loadingUnitComparisonResults!['match'] = false;
      return false;
    }
    unmatchedLoadingUnits.addAll(cachedLoadingUnits);
    final Set<int> addedNewIds = <int>{};
    for (final LoadingUnit genUnit in generatedLoadingUnits) {
      bool matched = false;
      for (final LoadingUnit cacheUnit in cachedLoadingUnits) {
        if (genUnit.equalsIgnoringPath(cacheUnit)) {
          matched = true;
          unmatchedLoadingUnits.remove(cacheUnit);
          break;
        }
      }
      if (!matched && !addedNewIds.contains(genUnit.id)) {
        newLoadingUnits.add(genUnit);
        addedNewIds.add(genUnit.id);
      }
    }
    loadingUnitComparisonResults!['new'] = newLoadingUnits;
    loadingUnitComparisonResults!['missing'] = unmatchedLoadingUnits;
    loadingUnitComparisonResults!['match'] = newLoadingUnits.isEmpty && unmatchedLoadingUnits.isEmpty;
    return loadingUnitComparisonResults!['match']! as bool;
  }

  List<LoadingUnit> _parseLoadingUnitsCache(File cacheFile) {
    final List<LoadingUnit> loadingUnits = <LoadingUnit>[];
    inputs.add(cacheFile);
    if (!cacheFile.existsSync()) {
      return loadingUnits;
    }
    final YamlMap data = loadYaml(cacheFile.readAsStringSync()) as YamlMap;
    // validate yaml format.
    if (!data.containsKey('loading-units')) {
      invalidFiles[cacheFile.path] = "Invalid loading units yaml file, 'loading-units' "
                                       'entry did not exist.';
      return loadingUnits;
    } else {
      if (data['loading-units'] is! YamlList && data['loading-units'] != null) {
        invalidFiles[cacheFile.path] = "Invalid loading units yaml file, 'loading-units' "
                                         'is not a list.';
        return loadingUnits;
      }
      if (data['loading-units'] != null) {
        for (final Object? loadingUnitData in data['loading-units']) {
          if (loadingUnitData is! YamlMap) {
            invalidFiles[cacheFile.path] = "Invalid loading units yaml file, 'loading-units' "
                                             'is not a list of maps.';
            return loadingUnits;
          }
          final YamlMap loadingUnitDataMap = loadingUnitData;
          if (loadingUnitDataMap['id'] == null) {
            invalidFiles[cacheFile.path] = 'Invalid loading units yaml file, all '
                                             "loading units must have an 'id'";
            return loadingUnits;
          }
          if (loadingUnitDataMap['libraries'] != null) {
            if (loadingUnitDataMap['libraries'] is! YamlList) {
              invalidFiles[cacheFile.path] = "Invalid loading units yaml file, 'libraries' "
                                               'is not a list.';
              return loadingUnits;
            }
            for (final Object? node in loadingUnitDataMap['libraries'] as YamlList) {
              if (node is! String) {
                invalidFiles[cacheFile.path] = "Invalid loading units yaml file, 'libraries' "
                                                 'is not a list of strings.';
                return loadingUnits;
              }
            }
          }
        }
      }
    }

    // Parse out validated yaml.
    if (data.containsKey('loading-units')) {
      if (data['loading-units'] != null) {
        for (final Object? loadingUnitData in data['loading-units']) {
          final YamlMap? loadingUnitDataMap = loadingUnitData as YamlMap?;
          final List<String> libraries = <String>[];
          final YamlList? nodes = loadingUnitDataMap?['libraries'] as YamlList?;
          if (nodes != null) {
            for (final Object node in nodes.whereType<Object>()) {
              libraries.add(node as String);
            }
          }
          loadingUnits.add(
              LoadingUnit(
                id: loadingUnitDataMap!['id'] as int,
                libraries: libraries,
              ));
        }
      }
    }
    return loadingUnits;
  }

  /// Writes the provided generatedLoadingUnits as `deferred_components_loading_units.yaml`
  ///
  /// This cache file is used to detect any changes in the loading units
  /// produced by gen_snapshot. Running [checkAgainstLoadingUnitCache] with a
  /// mismatching or missing cache will result in a failed validation. This
  /// prevents unexpected changes in loading units causing misconfigured
  /// deferred components.
  void writeLoadingUnitsCache(List<LoadingUnit>? generatedLoadingUnits) {
    generatedLoadingUnits ??= <LoadingUnit>[];
    final File cacheFile = projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName);
    outputs.add(cacheFile);
    ErrorHandlingFileSystem.deleteIfExists(cacheFile);
    cacheFile.createSync(recursive: true);

    final StringBuffer buffer = StringBuffer();
    buffer.write('''
# ==============================================================================
# The contents of this file are automatically generated and it is not
# recommended to modify this file manually.
# ==============================================================================
#
# In order to prevent unexpected splitting of deferred apps, this file records
# the last generated set of loading units. It only possible to obtain the final
# configuration of loading units after compilation is complete. This means
# improperly setup deferred imports can only be detected after compilation.
#
# This file allows the build tool to detect any changes in the generated
# loading units. During the next build attempt, loading units in this file are
# compared against the newly generated loading units to check for any new or
# removed loading units. In the case where loading units do not match, the build
# will fail and ask the developer to verify that the `deferred-components`
# configuration in `pubspec.yaml` is correct. Developers should make any
# necessary changes to integrate new and changed loading units or remove no
# longer existing loading units from the configuration. The build command should
# then be re-run to continue the build process.
#
# Sometimes, changes to the generated loading units may be unintentional. If
# the list of loading units in this file is not what is expected, the app's
# deferred imports should be reviewed. Third party plugins and packages may
# also introduce deferred imports that result in unexpected loading units.
loading-units:
''');
    final Set<int> usedIds = <int>{};
    for (final LoadingUnit unit in generatedLoadingUnits) {
      if (usedIds.contains(unit.id)) {
        continue;
      }
      buffer.write('  - id: ${unit.id}\n');
      if (unit.libraries != null && unit.libraries.isNotEmpty) {
        buffer.write('    libraries:\n');
        for (final String lib in unit.libraries) {
          buffer.write('      - $lib\n');
        }
      }
      usedIds.add(unit.id);
    }
    cacheFile.writeAsStringSync(buffer.toString(), flush: true);
  }
}
