// 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/file_system.dart';
import 'base/logger.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
import 'cache.dart';
import 'plugins.dart';

/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
class FlutterManifest {
  FlutterManifest._(this._logger);

  /// Returns an empty manifest.
  factory FlutterManifest.empty({ @required Logger logger }) {
    final FlutterManifest manifest = FlutterManifest._(logger);
    manifest._descriptor = const <String, dynamic>{};
    manifest._flutterDescriptor = const <String, dynamic>{};
    return manifest;
  }

  /// 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(loadYaml(manifest) as YamlMap, logger);
  }

  static FlutterManifest _createFromYaml(YamlMap yamlDocument, Logger logger) {
    final FlutterManifest pubspec = FlutterManifest._(logger);
    if (yamlDocument != null && !_validate(yamlDocument, logger)) {
      return null;
    }

    final Map<dynamic, dynamic> yamlMap = yamlDocument;
    if (yamlMap != null) {
      pubspec._descriptor = yamlMap.cast<String, dynamic>();
    } else {
      pubspec._descriptor = <String, dynamic>{};
    }

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

    return pubspec;
  }

  final Logger _logger;

  /// A map representation of the entire `pubspec.yaml` file.
  Map<String, dynamic> _descriptor;

  /// A map representation of the `flutter` section in the `pubspec.yaml` file.
  Map<String, dynamic> _flutterDescriptor;

  /// 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 ?? '';

  // 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 {
    if (appVersion != null && appVersion.contains('+')) {
      return appVersion.split('+')?.elementAt(0);
    }
    return appVersion;
  }

  /// 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 {
    if (appVersion != null && appVersion.contains('+')) {
      final String value = appVersion.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 {
    if (_flutterDescriptor.containsKey('module')) {
      return _flutterDescriptor['module']['androidX'] as bool;
    }
    return false;
  }

  /// 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) {
      return _flutterDescriptor['module']['androidPackage'] as String;
    }
    if (isPlugin) {
      final YamlMap plugin = _flutterDescriptor['plugin'] as YamlMap;
      if (plugin.containsKey('platforms')) {
        final YamlMap platforms = plugin['platforms'] as YamlMap;

        if (platforms.containsKey('android')) {
          return platforms['android']['package'] as String;
        }
      } else {
        return plugin['androidPackage'] as String;
      }
    }
    return null;
  }

  /// 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) {
      return _flutterDescriptor['module']['iosBundleIdentifier'] as String;
    }
    return null;
  }

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

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

  List<Uri> get assets => _assets ??= _computeAssets();
  List<Uri> _assets;
  List<Uri> _computeAssets() {
    final List<dynamic> assets = _flutterDescriptor['assets'] as List<dynamic>;
    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;
      }
      final String stringAsset = asset as String;
      try {
        results.add(Uri(pathSegments: stringAsset.split('/')));
      } on FormatException {
        _logger.printError('Asset manifest contains invalid uri: $asset.');
      }
    }
    return results;
  }

  List<Font> _fonts;

  List<Font> get fonts {
    _fonts ??= _extractFonts();
    return _fonts;
  }

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

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

      final List<FontAsset> fontAssets = <FontAsset>[];
      for (final Map<dynamic, dynamic> fontFile in fontFiles.cast<Map<dynamic, dynamic>>()) {
        final String asset = fontFile['asset'] as String;
        if (asset == null) {
          _logger.printError('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(fontFamily['family'] as String, fontAssets));
      }
    }
    return fonts;
  }
}

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, dynamic> get descriptor {
    return <String, dynamic>{
      'family': familyName,
      'fonts': fontAssets.map<Map<String, dynamic>>((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, dynamic> get descriptor {
    final Map<String, dynamic> descriptor = <String, dynamic>{};
    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)';
}

@visibleForTesting
String buildSchemaDir(FileSystem fileSystem) {
  return fileSystem.path.join(
    fileSystem.path.absolute(Cache.flutterRoot), 'packages', 'flutter_tools', 'schema',
  );
}

@visibleForTesting
String buildSchemaPath(FileSystem fileSystem) {
  return fileSystem.path.join(
    buildSchemaDir(fileSystem),
    'pubspec_yaml.json',
  );
}

/// This method should be kept in sync with the schema in
/// `$FLUTTER_ROOT/packages/flutter_tools/schema/pubspec_yaml.json`,
/// but avoid introducing dependencies on packages for simple validation.
bool _validate(YamlMap manifest, Logger logger) {
  final List<String> errors = <String>[];
  for (final MapEntry<dynamic, dynamic> 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<dynamic, dynamic> kvp in yaml.entries) {
    if (kvp.key is! String) {
      errors.add('Expected YAML key to be a string, but got ${kvp.key} (${kvp.value.runtimeType}).');
      continue;
    }
    switch (kvp.key as String) {
      case 'uses-material-design':
        if (kvp.value is! bool) {
          errors.add('Expected "${kvp.key}" to be a bool, but got ${kvp.value} (${kvp.value.runtimeType}).');
        }
        break;
      case 'assets':
      case 'services':
        if (kvp.value is! YamlList || kvp.value[0] is! String) {
          errors.add('Expected "${kvp.key}" to be a list, but got ${kvp.value} (${kvp.value.runtimeType}).');
        }
        break;
      case 'fonts':
        if (kvp.value is! YamlList || kvp.value[0] is! YamlMap) {
          errors.add('Expected "${kvp.key}" to be a list, but got ${kvp.value} (${kvp.value.runtimeType}).');
        } else {
          _validateFonts(kvp.value as YamlList, errors);
        }
        break;
      case 'module':
        if (kvp.value is! YamlMap) {
          errors.add('Expected "${kvp.key}" to be an object, but got ${kvp.value} (${kvp.value.runtimeType}).');
        }

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

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 dynamic fontListEntry in fonts) {
    if (fontListEntry is! YamlMap) {
      errors.add('Unexpected child "$fontListEntry" found under "fonts". Expected a map.');
      continue;
    }
    final YamlMap fontMap = fontListEntry as YamlMap;
    for (final dynamic key in fontMap.keys.where((dynamic 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 dynamic fontListItem in fontMap['fonts']) {
      if (fontListItem is! YamlMap) {
        errors.add('Expected "fonts" to be a list of maps.');
        continue;
      }
      final YamlMap fontMapList = fontListItem as YamlMap;
      for (final MapEntry<dynamic, dynamic> kvp in fontMapList.entries) {
        if (kvp.key is! String) {
          errors.add('Expected "${kvp.key}" under "fonts" to be a string.');
        }
        switch(kvp.key as String) {
          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 ${kvp.key} ((${kvp.value.runtimeType})) under font.');
            break;
        }
      }
    }
  }
}
