// Copyright (c) 2018, 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:checked_yaml/checked_yaml.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:pub_semver/pub_semver.dart';

import 'dependency.dart';
import 'screenshot.dart';

part 'pubspec.g.dart';

@JsonSerializable()
class Pubspec {
  // TODO: executables

  final String name;

  @JsonKey(fromJson: _versionFromString)
  final Version? version;

  final String? description;

  /// This should be a URL pointing to the website for the package.
  final String? homepage;

  /// Specifies where to publish this package.
  ///
  /// Accepted values: `null`, `'none'` or an `http` or `https` URL.
  ///
  /// [More information](https://dart.dev/tools/pub/pubspec#publish_to).
  final String? publishTo;

  /// Optional field to specify the source code repository of the package.
  /// Useful when a package has both a home page and a repository.
  final Uri? repository;

  /// Optional field to a web page where developers can report new issues or
  /// view existing ones.
  final Uri? issueTracker;

  /// Optional field to list the URLs where the package authors accept
  /// support or funding.
  final List<Uri>? funding;

  /// Optional field to list the topics that this packages belongs to.
  final List<String>? topics;

  /// Optional field for specifying included screenshot files.
  @JsonKey(fromJson: parseScreenshots)
  final List<Screenshot>? screenshots;

  /// If there is exactly 1 value in [authors], returns it.
  ///
  /// If there are 0 or more than 1, returns `null`.
  @Deprecated(
    'See https://dart.dev/tools/pub/pubspec#authorauthors',
  )
  String? get author {
    if (authors.length == 1) {
      return authors.single;
    }
    return null;
  }

  @Deprecated(
    'See https://dart.dev/tools/pub/pubspec#authorauthors',
  )
  final List<String> authors;
  final String? documentation;

  @JsonKey(fromJson: _environmentMap)
  final Map<String, VersionConstraint?>? environment;

  @JsonKey(fromJson: parseDeps)
  final Map<String, Dependency> dependencies;

  @JsonKey(fromJson: parseDeps)
  final Map<String, Dependency> devDependencies;

  @JsonKey(fromJson: parseDeps)
  final Map<String, Dependency> dependencyOverrides;

  /// Optional configuration specific to [Flutter](https://flutter.io/)
  /// packages.
  ///
  /// May include
  /// [assets](https://flutter.io/docs/development/ui/assets-and-images)
  /// and other settings.
  final Map<String, dynamic>? flutter;

  /// If [author] and [authors] are both provided, their values are combined
  /// with duplicates eliminated.
  Pubspec(
    this.name, {
    this.version,
    this.publishTo,
    @Deprecated(
      'See https://dart.dev/tools/pub/pubspec#authorauthors',
    )
        String? author,
    @Deprecated(
      'See https://dart.dev/tools/pub/pubspec#authorauthors',
    )
        List<String>? authors,
    Map<String, VersionConstraint?>? environment,
    this.homepage,
    this.repository,
    this.issueTracker,
    this.funding,
    this.topics,
    this.screenshots,
    this.documentation,
    this.description,
    Map<String, Dependency>? dependencies,
    Map<String, Dependency>? devDependencies,
    Map<String, Dependency>? dependencyOverrides,
    this.flutter,
  })  :
        // ignore: deprecated_member_use_from_same_package
        authors = _normalizeAuthors(author, authors),
        environment = environment ?? const {},
        dependencies = dependencies ?? const {},
        devDependencies = devDependencies ?? const {},
        dependencyOverrides = dependencyOverrides ?? const {} {
    if (name.isEmpty) {
      throw ArgumentError.value(name, 'name', '"name" cannot be empty.');
    }

    if (publishTo != null && publishTo != 'none') {
      try {
        final targetUri = Uri.parse(publishTo!);
        if (!(targetUri.isScheme('http') || targetUri.isScheme('https'))) {
          throw const FormatException('Must be an http or https URL.');
        }
      } on FormatException catch (e) {
        throw ArgumentError.value(publishTo, 'publishTo', e.message);
      }
    }
  }

  factory Pubspec.fromJson(Map json, {bool lenient = false}) {
    if (lenient) {
      while (json.isNotEmpty) {
        // Attempting to remove top-level properties that cause parsing errors.
        try {
          return _$PubspecFromJson(json);
        } on CheckedFromJsonException catch (e) {
          if (e.map == json && json.containsKey(e.key)) {
            json = Map.from(json)..remove(e.key);
            continue;
          }
          rethrow;
        }
      }
    }

    return _$PubspecFromJson(json);
  }

  /// Parses source [yaml] into [Pubspec].
  ///
  /// When [lenient] is set, top-level property-parsing or type cast errors are
  /// ignored and `null` values are returned.
  factory Pubspec.parse(String yaml, {Uri? sourceUrl, bool lenient = false}) =>
      checkedYamlDecode(
        yaml,
        (map) => Pubspec.fromJson(map!, lenient: lenient),
        sourceUrl: sourceUrl,
      );

  static List<String> _normalizeAuthors(String? author, List<String>? authors) {
    final value = <String>{
      if (author != null) author,
      ...?authors,
    };
    return value.toList();
  }
}

Version? _versionFromString(String? input) =>
    input == null ? null : Version.parse(input);

Map<String, VersionConstraint?>? _environmentMap(Map? source) =>
    source?.map((k, value) {
      final key = k as String;
      if (key == 'dart') {
        // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342
        // 'dart' is not allowed as a key!
        throw CheckedFromJsonException(
          source,
          'dart',
          'VersionConstraint',
          'Use "sdk" to for Dart SDK constraints.',
          badKey: true,
        );
      }

      VersionConstraint? constraint;
      if (value == null) {
        constraint = null;
      } else if (value is String) {
        try {
          constraint = VersionConstraint.parse(value);
        } on FormatException catch (e) {
          throw CheckedFromJsonException(source, key, 'Pubspec', e.message);
        }

        return MapEntry(key, constraint);
      } else {
        throw CheckedFromJsonException(
          source,
          key,
          'VersionConstraint',
          '`$value` is not a String.',
        );
      }

      return MapEntry(key, constraint);
    });
