// 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.

// @dart = 2.8

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);
      for (final LoadingUnit unit in component.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 = _parseLodingUnitsCache(projectDir.childFile(DeferredComponentsValidator.kLoadingUnitsCacheFileName));
    loadingUnitComparisonResults = <String, dynamic>{};
    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> _parseLodingUnitsCache(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 dynamic 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 as YamlMap;
          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 dynamic 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 dynamic loadingUnitData in data['loading-units']) {
          final YamlMap loadingUnitDataMap = loadingUnitData as YamlMap;
          final List<String> libraries = <String>[];
          if (loadingUnitDataMap['libraries'] != null) {
            for (final dynamic node in loadingUnitDataMap['libraries'] as YamlList) {
              libraries.add(node as String);
            }
          }
          loadingUnits.add(
              LoadingUnit(
                id: loadingUnitDataMap['id'] as int,
                path: null,
                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);
  }
}
