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

import 'base/deferred_component.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
import 'plugins.dart';

const Set<String> _kValidPluginPlatforms = <String>{
  'android', 'ios', 'web', 'windows', 'linux', 'macos'
};

/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
class FlutterManifest {
  FlutterManifest._({required Logger logger}) : _logger = logger;

  /// Returns an empty manifest.
  factory FlutterManifest.empty({ required Logger logger }) = FlutterManifest._;

  /// Returns null on invalid manifest. Returns empty manifest on missing file.
  static FlutterManifest? createFromPath(String path, {
    required FileSystem fileSystem,
    required Logger logger,
  }) {
    if (path == null || !fileSystem.isFileSync(path)) {
      return _createFromYaml(null, logger);
    }
    final String manifest = fileSystem.file(path).readAsStringSync();
    return FlutterManifest.createFromString(manifest, logger: logger);
  }

  /// Returns null on missing or invalid manifest.
  @visibleForTesting
  static FlutterManifest? createFromString(String manifest, { required Logger logger }) {
    return _createFromYaml(manifest != null ? loadYaml(manifest) : null, logger);
  }

  static FlutterManifest? _createFromYaml(Object? yamlDocument, Logger logger) {
    if (yamlDocument != null && !_validate(yamlDocument, logger)) {
      return null;
    }

    final FlutterManifest pubspec = FlutterManifest._(logger: logger);
    final Map<Object?, Object?>? yamlMap = yamlDocument as YamlMap?;
    if (yamlMap != null) {
      pubspec._descriptor = yamlMap.cast<String, Object?>();
    }

    final Map<Object?, Object?>? flutterMap = pubspec._descriptor['flutter'] as Map<Object?, Object?>?;
    if (flutterMap != null) {
      pubspec._flutterDescriptor = flutterMap.cast<String, Object?>();
    }

    return pubspec;
  }

  final Logger _logger;

  /// A map representation of the entire `pubspec.yaml` file.
  Map<String, Object?> _descriptor = <String, Object?>{};

  /// A map representation of the `flutter` section in the `pubspec.yaml` file.
  Map<String, Object?> _flutterDescriptor = <String, Object?>{};

  /// True if the `pubspec.yaml` file does not exist.
  bool get isEmpty => _descriptor.isEmpty;

  /// The string value of the top-level `name` property in the `pubspec.yaml` file.
  String get appName => _descriptor['name'] as String? ?? '';

  /// Contains the name of the dependencies.
  /// These are the keys specified in the `dependency` map.
  Set<String> get dependencies {
    final YamlMap? dependencies = _descriptor['dependencies'] as YamlMap?;
    return dependencies != null ? <String>{...dependencies.keys.cast<String>()} : <String>{};
  }

  // Flag to avoid printing multiple invalid version messages.
  bool _hasShowInvalidVersionMsg = false;

  /// The version String from the `pubspec.yaml` file.
  /// Can be null if it isn't set or has a wrong format.
  String? get appVersion {
    final String? verStr = _descriptor['version']?.toString();
    if (verStr == null) {
      return null;
    }

    Version? version;
    try {
      version = Version.parse(verStr);
    } on Exception {
      if (!_hasShowInvalidVersionMsg) {
        _logger.printStatus(userMessages.invalidVersionSettingHintMessage(verStr), emphasis: true);
        _hasShowInvalidVersionMsg = true;
      }
    }
    return version?.toString();
  }

  /// The build version name from the `pubspec.yaml` file.
  /// Can be null if version isn't set or has a wrong format.
  String? get buildName {
    final String? version = appVersion;
    if (version != null && version.contains('+')) {
      return version.split('+').elementAt(0);
    }
    return version;
  }

  /// The build version number from the `pubspec.yaml` file.
  /// Can be null if version isn't set or has a wrong format.
  String? get buildNumber {
    final String? version = appVersion;
    if (version != null && version.contains('+')) {
      final String value = version.split('+').elementAt(1);
      return value;
    } else {
      return null;
    }
  }

  bool get usesMaterialDesign {
    return _flutterDescriptor['uses-material-design'] as bool? ?? false;
  }

  /// True if this Flutter module should use AndroidX dependencies.
  ///
  /// If false the deprecated Android Support library will be used.
  bool get usesAndroidX {
    final Object? module = _flutterDescriptor['module'];
    if (module is YamlMap) {
      return module['androidX'] == true;
    }
    return false;
  }

  /// Any additional license files listed under the `flutter` key.
  ///
  /// This is expected to be a list of file paths that should be treated as
  /// relative to the pubspec in this directory.
  ///
  /// For example:
  ///
  /// ```yaml
  /// flutter:
  ///   licenses:
  ///     - assets/foo_license.txt
  /// ```
  List<String> get additionalLicenses {
    final Object? licenses = _flutterDescriptor['licenses'];
    if (licenses is YamlList) {
      return licenses.map((Object? element) => element.toString()).toList();
    }
    return <String>[];
  }

  /// True if this manifest declares a Flutter module project.
  ///
  /// A Flutter project is considered a module when it has a `module:`
  /// descriptor. A Flutter module project supports integration into an
  /// existing host app, and has managed platform host code.
  ///
  /// Such a project can be created using `flutter create -t module`.
  bool get isModule => _flutterDescriptor.containsKey('module');

  /// True if this manifest declares a Flutter plugin project.
  ///
  /// A Flutter project is considered a plugin when it has a `plugin:`
  /// descriptor. A Flutter plugin project wraps custom Android and/or
  /// iOS code in a Dart interface for consumption by other Flutter app
  /// projects.
  ///
  /// Such a project can be created using `flutter create -t plugin`.
  bool get isPlugin => _flutterDescriptor.containsKey('plugin');

  /// Returns the Android package declared by this manifest in its
  /// module or plugin descriptor. Returns null, if there is no
  /// such declaration.
  String? get androidPackage {
    if (isModule) {
      final Object? module = _flutterDescriptor['module'];
      if (module is YamlMap) {
        return module['androidPackage'] as String?;
      }
    }
    final Map<String, Object?>? platforms = supportedPlatforms;
    if (platforms == null) {
      // Pre-multi-platform plugin format
      if (isPlugin) {
        final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?;
        return plugin?['androidPackage'] as String?;
      }
      return null;
    }
    if (platforms.containsKey('android')) {
      final Object? android = platforms['android'];
      if (android is YamlMap) {
        return android['package'] as String?;
      }
    }
    return null;
  }

  /// Returns the deferred components configuration if declared. Returns
  /// null if no deferred components are declared.
  late final List<DeferredComponent>? deferredComponents = computeDeferredComponents();
  List<DeferredComponent>? computeDeferredComponents() {
    if (!_flutterDescriptor.containsKey('deferred-components')) {
      return null;
    }
    final List<DeferredComponent> components = <DeferredComponent>[];
    final Object? deferredComponents = _flutterDescriptor['deferred-components'];
    if (deferredComponents is! YamlList) {
      return components;
    }
    for (final Object? component in deferredComponents) {
      if (component is! YamlMap) {
        _logger.printError('Expected deferred component manifest to be a map.');
        continue;
      }
      List<Uri> assetsUri = <Uri>[];
      final List<Object?>? assets = component['assets'] as List<Object?>?;
      if (assets == null) {
        assetsUri = const <Uri>[];
      } else {
        for (final Object? asset in assets) {
          if (asset is! String || asset == null || asset == '') {
            _logger.printError('Deferred component asset manifest contains a null or empty uri.');
            continue;
          }
          try {
            assetsUri.add(Uri.parse(asset));
          } on FormatException {
            _logger.printError('Asset manifest contains invalid uri: $asset.');
          }
        }
      }
      components.add(
        DeferredComponent(
          name: component['name'] as String,
          libraries: component['libraries'] == null ?
              <String>[] : (component['libraries'] as List<dynamic>).cast<String>(),
          assets: assetsUri,
        )
      );
    }
    return components;
  }

  /// Returns the iOS bundle identifier declared by this manifest in its
  /// module descriptor. Returns null if there is no such declaration.
  String? get iosBundleIdentifier {
    if (isModule) {
      final Object? module = _flutterDescriptor['module'];
      if (module is YamlMap) {
        return module['iosBundleIdentifier'] as String?;
      }
    }
    return null;
  }

  /// Gets the supported platforms. This only supports the new `platforms` format.
  ///
  /// If the plugin uses the legacy pubspec format, this method returns null.
  Map<String, Object?>? get supportedPlatforms {
    if (isPlugin) {
      final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?;
      if (plugin?.containsKey('platforms') ?? false) {
        final YamlMap? platformsMap = plugin!['platforms'] as YamlMap?;
        return platformsMap?.value.cast<String, Object?>();
      }
    }
    return null;
  }

  /// Like [supportedPlatforms], but only returns the valid platforms that are supported in flutter plugins.
  Map<String, Object?>? get validSupportedPlatforms {
    final Map<String, Object?>? allPlatforms = supportedPlatforms;
    if (allPlatforms == null) {
      return null;
    }
    final Map<String, Object?> platforms = <String, Object?>{}..addAll(allPlatforms);
    platforms.removeWhere((String key, Object? _) => !_kValidPluginPlatforms.contains(key));
    if (platforms.isEmpty) {
      return null;
    }
    return platforms;
  }

  List<Map<String, Object?>> get fontsDescriptor {
    return fonts.map((Font font) => font.descriptor).toList();
  }

  List<Map<String, Object?>> get _rawFontsDescriptor {
    final List<Object?>? fontList = _flutterDescriptor['fonts'] as List<Object?>?;
    return fontList == null
        ? const <Map<String, Object?>>[]
        : fontList.map<Map<String, Object?>?>(castStringKeyedMap).whereType<Map<String, Object?>>().toList();
  }

  late final List<Uri> assets = _computeAssets();
  List<Uri> _computeAssets() {
    final List<Object?>? assets = _flutterDescriptor['assets'] as List<Object?>?;
    if (assets == null) {
      return const <Uri>[];
    }
    final List<Uri> results = <Uri>[];
    for (final Object? asset in assets) {
      if (asset is! String || asset == null || asset == '') {
        _logger.printError('Asset manifest contains a null or empty uri.');
        continue;
      }
      try {
        results.add(Uri(pathSegments: asset.split('/')));
      } on FormatException {
        _logger.printError('Asset manifest contains invalid uri: $asset.');
      }
    }
    return results;
  }

  late final List<Font> fonts = _extractFonts();

  List<Font> _extractFonts() {
    if (!_flutterDescriptor.containsKey('fonts')) {
      return <Font>[];
    }

    final List<Font> fonts = <Font>[];
    for (final Map<String, Object?> fontFamily in _rawFontsDescriptor) {
      final YamlList? fontFiles = fontFamily['fonts'] as YamlList?;
      final String? familyName = fontFamily['family'] as String?;
      if (familyName == null) {
        _logger.printWarning('Warning: Missing family name for font.', emphasis: true);
        continue;
      }
      if (fontFiles == null) {
        _logger.printWarning('Warning: No fonts specified for font $familyName', emphasis: true);
        continue;
      }

      final List<FontAsset> fontAssets = <FontAsset>[];
      for (final Map<Object?, Object?> fontFile in fontFiles.cast<Map<Object?, Object?>>()) {
        final String? asset = fontFile['asset'] as String?;
        if (asset == null) {
          _logger.printWarning('Warning: Missing asset in fonts for $familyName', emphasis: true);
          continue;
        }

        fontAssets.add(FontAsset(
          Uri.parse(asset),
          weight: fontFile['weight'] as int?,
          style: fontFile['style'] as String?,
        ));
      }
      if (fontAssets.isNotEmpty) {
        fonts.add(Font(familyName, fontAssets));
      }
    }
    return fonts;
  }

  /// Whether a synthetic flutter_gen package should be generated.
  ///
  /// This can be provided to the [Pub] interface to inject a new entry
  /// into the package_config.json file which points to `.dart_tool/flutter_gen`.
  ///
  /// This allows generated source code to be imported using a package
  /// alias.
  late final bool generateSyntheticPackage = _computeGenerateSyntheticPackage();
  bool _computeGenerateSyntheticPackage() {
    if (!_flutterDescriptor.containsKey('generate')) {
      return false;
    }
    final Object? value = _flutterDescriptor['generate'];
    if (value is! bool) {
      return false;
    }
    return value;
  }
}

class Font {
  Font(this.familyName, this.fontAssets)
    : assert(familyName != null),
      assert(fontAssets != null),
      assert(fontAssets.isNotEmpty);

  final String familyName;
  final List<FontAsset> fontAssets;

  Map<String, Object?> get descriptor {
    return <String, Object?>{
      'family': familyName,
      'fonts': fontAssets.map<Map<String, Object?>>((FontAsset a) => a.descriptor).toList(),
    };
  }

  @override
  String toString() => '$runtimeType(family: $familyName, assets: $fontAssets)';
}

class FontAsset {
  FontAsset(this.assetUri, {this.weight, this.style})
    : assert(assetUri != null);

  final Uri assetUri;
  final int? weight;
  final String? style;

  Map<String, Object?> get descriptor {
    final Map<String, Object?> descriptor = <String, Object?>{};
    if (weight != null) {
      descriptor['weight'] = weight;
    }

    if (style != null) {
      descriptor['style'] = style;
    }

    descriptor['asset'] = assetUri.path;
    return descriptor;
  }

  @override
  String toString() => '$runtimeType(asset: ${assetUri.path}, weight; $weight, style: $style)';
}


bool _validate(Object? manifest, Logger logger) {
  final List<String> errors = <String>[];
  if (manifest is! YamlMap) {
    errors.add('Expected YAML map');
  } else {
    for (final MapEntry<Object?, Object?> kvp in manifest.entries) {
      if (kvp.key is! String) {
        errors.add('Expected YAML key to be a string, but got ${kvp.key}.');
        continue;
      }
      switch (kvp.key as String?) {
        case 'name':
          if (kvp.value is! String) {
            errors.add('Expected "${kvp.key}" to be a string, but got ${kvp.value}.');
          }
          break;
        case 'flutter':
          if (kvp.value == null) {
            continue;
          }
          if (kvp.value is! YamlMap) {
            errors.add('Expected "${kvp.key}" section to be an object or null, but got ${kvp.value}.');
          } else {
            _validateFlutter(kvp.value as YamlMap?, errors);
          }
          break;
        default:
        // additionalProperties are allowed.
          break;
      }
    }
  }

  if (errors.isNotEmpty) {
    logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
    logger.printError(errors.join('\n'));
    return false;
  }

  return true;
}

void _validateFlutter(YamlMap? yaml, List<String> errors) {
  if (yaml == null || yaml.entries == null) {
    return;
  }
  for (final MapEntry<Object?, Object?> kvp in yaml.entries) {
    final Object? yamlKey = kvp.key;
    final Object? yamlValue = kvp.value;
    if (yamlKey is! String) {
      errors.add('Expected YAML key to be a string, but got $yamlKey (${yamlValue.runtimeType}).');
      continue;
    }
    switch (yamlKey) {
      case 'uses-material-design':
        if (yamlValue is! bool) {
          errors.add('Expected "$yamlKey" to be a bool, but got $yamlValue (${yamlValue.runtimeType}).');
        }
        break;
      case 'assets':
        if (yamlValue is! YamlList) {

          errors.add('Expected "$yamlKey" to be a list, but got $yamlValue (${yamlValue.runtimeType}).');
        } else if (yamlValue.isEmpty) {
          break;
        } else if (yamlValue[0] is! String) {
          errors.add(
            'Expected "$yamlKey" to be a list of strings, but the first element is $yamlValue (${yamlValue.runtimeType}).',
          );
        }
        break;
      case 'fonts':
        if (yamlValue is! YamlList) {
          errors.add('Expected "$yamlKey" to be a list, but got $yamlValue (${yamlValue.runtimeType}).');
        } else if (yamlValue.isEmpty) {
          break;
        } else if (yamlValue.first is! YamlMap) {
          errors.add(
            'Expected "$yamlKey" to contain maps, but the first element is $yamlValue (${yamlValue.runtimeType}).',
          );
        } else {
          _validateFonts(yamlValue, errors);
        }
        break;
      case 'licenses':
        if (yamlValue is! YamlList) {
          errors.add('Expected "$yamlKey" to be a list of files, but got $yamlValue (${yamlValue.runtimeType})');
        } else if (yamlValue.isEmpty) {
          break;
        } else if (yamlValue.first is! String) {
          errors.add(
            'Expected "$yamlKey" to contain strings, but the first element is $yamlValue (${yamlValue.runtimeType}).',
          );
        } else {
          _validateListType<String>(yamlValue, errors, '"$yamlKey"', 'files');
        }
        break;
      case 'module':
        if (yamlValue is! YamlMap) {
          errors.add('Expected "$yamlKey" to be an object, but got $yamlValue (${yamlValue.runtimeType}).');
          break;
        }

        if (yamlValue['androidX'] != null && yamlValue['androidX'] is! bool) {
          errors.add('The "androidX" value must be a bool if set.');
        }
        if (yamlValue['androidPackage'] != null && yamlValue['androidPackage'] is! String) {
          errors.add('The "androidPackage" value must be a string if set.');
        }
        if (yamlValue['iosBundleIdentifier'] != null && yamlValue['iosBundleIdentifier'] is! String) {
          errors.add('The "iosBundleIdentifier" section must be a string if set.');
        }
        break;
      case 'plugin':
        if (yamlValue is! YamlMap || yamlValue == null) {
          errors.add('Expected "$yamlKey" to be an object, but got $yamlValue (${yamlValue.runtimeType}).');
          break;
        }
        final List<String> pluginErrors = Plugin.validatePluginYaml(yamlValue);
        errors.addAll(pluginErrors);
        break;
      case 'generate':
        break;
      case 'deferred-components':
        _validateDeferredComponents(kvp, errors);
        break;
      default:
        errors.add('Unexpected child "$yamlKey" found under "flutter".');
        break;
    }
  }
}

void _validateListType<T>(YamlList yamlList, List<String> errors, String context, String typeAlias) {
  for (int i = 0; i < yamlList.length; i++) {
    if (yamlList[i] is! T) {
      // ignore: avoid_dynamic_calls
      errors.add('Expected $context to be a list of $typeAlias, but element $i was a ${yamlList[i].runtimeType}');
    }
  }
}

void _validateDeferredComponents(MapEntry<Object?, Object?> kvp, List<String> errors) {
  final Object? yamlList = kvp.value;
  if (yamlList != null && (yamlList is! YamlList || yamlList[0] is! YamlMap)) {
    errors.add('Expected "${kvp.key}" to be a list, but got $yamlList (${yamlList.runtimeType}).');
  } else if (yamlList is YamlList) {
    for (int i = 0; i < yamlList.length; i++) {
      final Object? valueMap = yamlList[i];
      if (valueMap is! YamlMap) {
        // ignore: avoid_dynamic_calls
        errors.add('Expected the $i element in "${kvp.key}" to be a map, but got ${yamlList[i]} (${yamlList[i].runtimeType}).');
        continue;
      }
      if (!valueMap.containsKey('name') || valueMap['name'] is! String) {
        errors.add('Expected the $i element in "${kvp.key}" to have required key "name" of type String');
      }
      if (valueMap.containsKey('libraries')) {
        final Object? libraries = valueMap['libraries'];
        if (libraries is! YamlList) {
          errors.add('Expected "libraries" key in the $i element of "${kvp.key}" to be a list, but got $libraries (${libraries.runtimeType}).');
        } else {
          _validateListType<String>(libraries, errors, '"libraries" key in the $i element of "${kvp.key}"', 'dart library Strings');
        }
      }
      if (valueMap.containsKey('assets')) {
        final Object? assets = valueMap['assets'];
        if (assets is! YamlList) {
          errors.add('Expected "assets" key in the $i element of "${kvp.key}" to be a list, but got $assets (${assets.runtimeType}).');
        } else {
          _validateListType<String>(assets, errors, '"assets" key in the $i element of "${kvp.key}"', 'file paths');
        }
      }
    }
  }
}

void _validateFonts(YamlList fonts, List<String> errors) {
  if (fonts == null) {
    return;
  }
  const Set<int> fontWeights = <int>{
    100, 200, 300, 400, 500, 600, 700, 800, 900,
  };
  for (final Object? fontMap in fonts) {
    if (fontMap is! YamlMap) {
      errors.add('Unexpected child "$fontMap" found under "fonts". Expected a map.');
      continue;
    }
    for (final Object? key in fontMap.keys.where((Object? key) => key != 'family' && key != 'fonts')) {
      errors.add('Unexpected child "$key" found under "fonts".');
    }
    if (fontMap['family'] != null && fontMap['family'] is! String) {
      errors.add('Font family must either be null or a String.');
    }
    if (fontMap['fonts'] == null) {
      continue;
    } else if (fontMap['fonts'] is! YamlList) {
      errors.add('Expected "fonts" to either be null or a list.');
      continue;
    }
    for (final Object? fontMapList in fontMap['fonts'] as List<Object?>) {
      if (fontMapList is! YamlMap) {
        errors.add('Expected "fonts" to be a list of maps.');
        continue;
      }
      for (final MapEntry<Object?, Object?> kvp in fontMapList.entries) {
        final Object? fontKey = kvp.key;
        if (fontKey is! String) {
          errors.add('Expected "$fontKey" under "fonts" to be a string.');
        }
        switch(fontKey) {
          case 'asset':
            if (kvp.value is! String) {
              errors.add('Expected font asset ${kvp.value} ((${kvp.value.runtimeType})) to be a string.');
            }
            break;
          case 'weight':
            if (!fontWeights.contains(kvp.value)) {
              errors.add('Invalid value ${kvp.value} ((${kvp.value.runtimeType})) for font -> weight.');
            }
            break;
          case 'style':
            if (kvp.value != 'normal' && kvp.value != 'italic') {
              errors.add('Invalid value ${kvp.value} ((${kvp.value.runtimeType})) for font -> style.');
            }
            break;
          default:
            errors.add('Unexpected key $fontKey ((${kvp.value.runtimeType})) under font.');
            break;
        }
      }
    }
  }
}
