// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. 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 'language_version.dart';

/// Contents of a `.dart_tool/package_config.json` file.
class PackageConfig {
  /// Version of the configuration in the `.dart_tool/package_config.json` file.
  ///
  /// The only supported value as of writing is `2`.
  int configVersion;

  /// Packages configured.
  List<PackageConfigEntry> packages;

  /// Date-time the `.dart_tool/package_config.json` file was generated.
  ///
  /// This property is **optional** and may be `null` if not given.
  DateTime generated;

  /// Tool that generated the `.dart_tool/package_config.json` file.
  ///
  /// For `pub` this is always `'pub'`.
  ///
  /// This property is **optional** and may be `null` if not given.
  String generator;

  /// Version of the tool that generated the `.dart_tool/package_config.json`
  /// file.
  ///
  /// For `pub` this is the Dart SDK version from which `pub get` was called.
  ///
  /// This property is **optional** and may be `null` if not given.
  Version generatorVersion;

  /// Additional properties not in the specification for the
  /// `.dart_tool/package_config.json` file.
  Map<String, dynamic> additionalProperties;

  PackageConfig({
    @required this.configVersion,
    @required this.packages,
    this.generated,
    this.generator,
    this.generatorVersion,
    this.additionalProperties,
  }) {
    additionalProperties ??= {};
  }

  /// Create [PackageConfig] from JSON [data].
  ///
  /// Throws [FormatException], if format is invalid, this does not validate the
  /// contents only that the format is correct.
  factory PackageConfig.fromJson(Object data) {
    if (data is! Map<String, dynamic>) {
      throw FormatException('package_config.json must be a JSON object');
    }
    final root = data as Map<String, dynamic>;

    void _throw(String property, String mustBe) => throw FormatException(
        '"$property" in .dart_tool/package_config.json $mustBe');

    /// Read the 'configVersion' property
    final configVersion = root['configVersion'];
    if (configVersion is! int) {
      _throw('configVersion', 'must be an integer');
    }
    if (configVersion != 2) {
      _throw('configVersion', 'must be 2 (the only supported version)');
    }

    final packagesRaw = root['packages'];
    if (packagesRaw is! List) {
      _throw('packages', 'must be a list');
    }
    final packages = <PackageConfigEntry>[];
    for (final entry in packagesRaw) {
      packages.add(PackageConfigEntry.fromJson(entry));
    }

    // Read the 'generated' property
    DateTime generated;
    final generatedRaw = root['generated'];
    if (generatedRaw != null) {
      if (generatedRaw is! String) {
        _throw('generated', 'must be a string, if given');
      }
      generated = DateTime.parse(generatedRaw);
    }

    // Read the 'generator' property
    final generator = root['generator'];
    if (generator != null && generator is! String) {
      throw FormatException(
          '"generator" in package_config.json must be a string, if given');
    }

    // Read the 'generatorVersion' property
    Version generatorVersion;
    final generatorVersionRaw = root['generatorVersion'];
    if (generatorVersionRaw != null) {
      if (generatorVersionRaw is! String) {
        _throw('generatorVersion', 'must be a string, if given');
      }
      try {
        generatorVersion = Version.parse(generatorVersionRaw);
      } on FormatException catch (e) {
        _throw('generatorVersion',
            'must be a semver version, if given, error: ${e.message}');
      }
    }

    return PackageConfig(
        configVersion: configVersion as int,
        packages: packages,
        generated: generated,
        generator: generator,
        generatorVersion: generatorVersion,
        additionalProperties: Map.fromEntries(root.entries.where((e) => !{
              'configVersion',
              'packages',
              'generated',
              'generator',
              'generatorVersion',
            }.contains(e.key))));
  }

  /// Convert to JSON structure.
  Map<String, Object> toJson() => {
        'configVersion': configVersion,
        'packages': packages.map((p) => p.toJson()).toList(),
        'generated': generated?.toUtc()?.toIso8601String(),
        'generator': generator,
        'generatorVersion': generatorVersion?.toString(),
      }..addAll(additionalProperties ?? {});
}

class PackageConfigEntry {
  /// Package name.
  String name;

  /// Root [Uri] of the package.
  ///
  /// This specifies the root folder of the package, all files below this folder
  /// is considered part of this package.
  Uri rootUri;

  /// Relative URI path of the library folder relative to [rootUri].
  ///
  /// Import statements in Dart programs are resolved relative to this folder.
  /// This must be in the sub-tree under [rootUri].
  ///
  /// This property is **optional** and may be `null` if not given.
  Uri packageUri;

  /// Language version used by package.
  ///
  /// Given as `<major>.<minor>` version, similar to the `// @dart = X.Y`
  /// comment. This is derived from the lower-bound on the Dart SDK requirement
  /// in the `pubspec.yaml` for the given package.
  ///
  /// This property is **optional** and may be `null` if not given.
  LanguageVersion languageVersion;

  /// Additional properties not in the specification for the
  /// `.dart_tool/package_config.json` file.
  Map<String, dynamic> additionalProperties;

  PackageConfigEntry({
    @required this.name,
    @required this.rootUri,
    this.packageUri,
    this.languageVersion,
    this.additionalProperties,
  }) {
    additionalProperties ??= {};
  }

  /// Create [PackageConfigEntry] from JSON [data].
  ///
  /// Throws [FormatException], if format is invalid, this does not validate the
  /// contents only that the format is correct.
  factory PackageConfigEntry.fromJson(Object data) {
    if (data is! Map<String, dynamic>) {
      throw FormatException(
          'packages[] entries in package_config.json must be JSON objects');
    }
    final root = data as Map<String, dynamic>;

    void _throw(String property, String mustBe) => throw FormatException(
        '"packages[].$property" in .dart_tool/package_config.json $mustBe');

    final name = root['name'];
    if (name is! String) {
      _throw('name', 'must be a string');
    }

    Uri rootUri;
    final rootUriRaw = root['rootUri'];
    if (rootUriRaw is! String) {
      _throw('rootUri', 'must be a string');
    }
    try {
      rootUri = Uri.parse(rootUriRaw);
    } on FormatException {
      _throw('rootUri', 'must be a URI');
    }

    Uri packageUri;
    final packageUriRaw = root['packageUri'];
    if (packageUriRaw != null) {
      if (packageUriRaw is! String) {
        _throw('packageUri', 'must be a string');
      }
      try {
        packageUri = Uri.parse(packageUriRaw);
      } on FormatException {
        _throw('packageUri', 'must be a URI');
      }
    }

    LanguageVersion languageVersion;
    final languageVersionRaw = root['languageVersion'];
    if (languageVersionRaw != null) {
      if (languageVersionRaw is! String) {
        _throw('languageVersion', 'must be a string');
      }
      try {
        languageVersion = LanguageVersion.parse(languageVersionRaw);
      } on FormatException {
        _throw('languageVersion', 'must be on the form <major>.<minor>');
      }
    }

    return PackageConfigEntry(
      name: name,
      rootUri: rootUri,
      packageUri: packageUri,
      languageVersion: languageVersion,
    );
  }

  /// Convert to JSON structure.
  Map<String, Object> toJson() => {
        'name': name,
        'rootUri': rootUri.toString(),
        if (packageUri != null) 'packageUri': packageUri?.toString(),
        if (languageVersion != null) 'languageVersion': '$languageVersion',
      }..addAll(additionalProperties ?? {});
}
