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

// Parsing and serialization of package configurations.

import 'dart:convert';
import 'dart:typed_data';

import 'errors.dart';
import 'package_config_impl.dart';
import 'packages_file.dart' as packages_file;
import 'util.dart';

const String _configVersionKey = 'configVersion';
const String _packagesKey = 'packages';
const List<String> _topNames = [_configVersionKey, _packagesKey];
const String _nameKey = 'name';
const String _rootUriKey = 'rootUri';
const String _packageUriKey = 'packageUri';
const String _languageVersionKey = 'languageVersion';
const List<String> _packageNames = [
  _nameKey,
  _rootUriKey,
  _packageUriKey,
  _languageVersionKey
];

const String _generatedKey = 'generated';
const String _generatorKey = 'generator';
const String _generatorVersionKey = 'generatorVersion';

final _jsonUtf8Decoder = json.fuse(utf8).decoder;

PackageConfig parsePackageConfigBytes(
    Uint8List bytes, Uri file, void Function(Object error) onError) {
  // TODO(lrn): Make this simpler. Maybe parse directly from bytes.
  Object? jsonObject;
  try {
    jsonObject = _jsonUtf8Decoder.convert(bytes);
  } on FormatException catch (e) {
    onError(PackageConfigFormatException.from(e));
    return const SimplePackageConfig.empty();
  }
  return parsePackageConfigJson(jsonObject, file, onError);
}

PackageConfig parsePackageConfigString(
    String source, Uri file, void Function(Object error) onError) {
  Object? jsonObject;
  try {
    jsonObject = jsonDecode(source);
  } on FormatException catch (e) {
    onError(PackageConfigFormatException.from(e));
    return const SimplePackageConfig.empty();
  }
  return parsePackageConfigJson(jsonObject, file, onError);
}

/// Creates a [PackageConfig] from a parsed JSON-like object structure.
///
/// The [json] argument must be a JSON object (`Map<String, Object?>`)
/// containing a `"configVersion"` entry with an integer value in the range
/// 1 to [PackageConfig.maxVersion],
/// and with a `"packages"` entry which is a JSON array (`List<Object?>`)
/// containing JSON objects which each has the following properties:
///
/// * `"name"`: The package name as a string.
/// * `"rootUri"`: The root of the package as a URI stored as a string.
/// * `"packageUri"`: Optionally the root of for `package:` URI resolution
///     for the package, as a relative URI below the root URI
///     stored as a string.
/// * `"languageVersion"`: Optionally a language version string which is a
///     an integer numeral, a decimal point (`.`) and another integer numeral,
///     where the integer numeral cannot have a sign, and can only have a
///     leading zero if the entire numeral is a single zero.
///
/// The [baseLocation] is used as base URI to resolve the "rootUri"
/// URI reference string.
PackageConfig parsePackageConfigJson(
    Object? json, Uri baseLocation, void Function(Object error) onError) {
  if (!baseLocation.hasScheme || baseLocation.isScheme('package')) {
    throw PackageConfigArgumentError(baseLocation.toString(), 'baseLocation',
        'Must be an absolute non-package: URI');
  }

  if (!baseLocation.path.endsWith('/')) {
    baseLocation = baseLocation.resolveUri(Uri(path: '.'));
  }

  String typeName<T>() {
    if (0 is T) return 'int';
    if ('' is T) return 'string';
    if (const <Object?>[] is T) return 'array';
    return 'object';
  }

  T? checkType<T>(Object? value, String name, [String? packageName]) {
    if (value is T) return value;
    // The only types we are called with are [int], [String], [List<Object?>]
    // and Map<String, Object?>. Recognize which to give a better error message.
    var message =
        "$name${packageName != null ? " of package $packageName" : ""}"
        ' is not a JSON ${typeName<T>()}';
    onError(PackageConfigFormatException(message, value));
    return null;
  }

  Package? parsePackage(Map<String, Object?> entry) {
    String? name;
    String? rootUri;
    String? packageUri;
    String? languageVersion;
    Map<String, Object?>? extraData;
    var hasName = false;
    var hasRoot = false;
    var hasVersion = false;
    entry.forEach((key, value) {
      switch (key) {
        case _nameKey:
          hasName = true;
          name = checkType<String>(value, _nameKey);
          break;
        case _rootUriKey:
          hasRoot = true;
          rootUri = checkType<String>(value, _rootUriKey, name);
          break;
        case _packageUriKey:
          packageUri = checkType<String>(value, _packageUriKey, name);
          break;
        case _languageVersionKey:
          hasVersion = true;
          languageVersion = checkType<String>(value, _languageVersionKey, name);
          break;
        default:
          (extraData ??= {})[key] = value;
          break;
      }
    });
    if (!hasName) {
      onError(PackageConfigFormatException('Missing name entry', entry));
    }
    if (!hasRoot) {
      onError(PackageConfigFormatException('Missing rootUri entry', entry));
    }
    if (name == null || rootUri == null) return null;
    var parsedRootUri = Uri.parse(rootUri!);
    var relativeRoot = !hasAbsolutePath(parsedRootUri);
    var root = baseLocation.resolveUri(parsedRootUri);
    if (!root.path.endsWith('/')) root = root.replace(path: '${root.path}/');
    var packageRoot = root;
    if (packageUri != null) packageRoot = root.resolve(packageUri!);
    if (!packageRoot.path.endsWith('/')) {
      packageRoot = packageRoot.replace(path: '${packageRoot.path}/');
    }

    LanguageVersion? version;
    if (languageVersion != null) {
      version = parseLanguageVersion(languageVersion, onError);
    } else if (hasVersion) {
      version = SimpleInvalidLanguageVersion('invalid');
    }

    return SimplePackage.validate(
        name!, root, packageRoot, version, extraData, relativeRoot, (error) {
      if (error is ArgumentError) {
        onError(
          PackageConfigFormatException(
              error.message.toString(), error.invalidValue),
        );
      } else {
        onError(error);
      }
    });
  }

  var map = checkType<Map<String, Object?>>(json, 'value');
  if (map == null) return const SimplePackageConfig.empty();
  Map<String, Object?>? extraData;
  List<Package>? packageList;
  int? configVersion;
  map.forEach((key, value) {
    switch (key) {
      case _configVersionKey:
        configVersion = checkType<int>(value, _configVersionKey) ?? 2;
        break;
      case _packagesKey:
        var packageArray = checkType<List<Object?>>(value, _packagesKey) ?? [];
        var packages = <Package>[];
        for (var package in packageArray) {
          var packageMap =
              checkType<Map<String, Object?>>(package, 'package entry');
          if (packageMap != null) {
            var entry = parsePackage(packageMap);
            if (entry != null) {
              packages.add(entry);
            }
          }
        }
        packageList = packages;
        break;
      default:
        (extraData ??= {})[key] = value;
        break;
    }
  });
  if (configVersion == null) {
    onError(PackageConfigFormatException('Missing configVersion entry', json));
    configVersion = 2;
  }
  if (packageList == null) {
    onError(PackageConfigFormatException('Missing packages list', json));
    packageList = [];
  }
  return SimplePackageConfig(configVersion!, packageList!, extraData, (error) {
    if (error is ArgumentError) {
      onError(
        PackageConfigFormatException(
            error.message.toString(), error.invalidValue),
      );
    } else {
      onError(error);
    }
  });
}

final _jsonUtf8Encoder = JsonUtf8Encoder('  ');

void writePackageConfigJsonUtf8(
    PackageConfig config, Uri? baseUri, Sink<List<int>> output) {
  // Can be optimized.
  var data = packageConfigToJson(config, baseUri);
  output.add(_jsonUtf8Encoder.convert(data) as Uint8List);
}

void writePackageConfigJsonString(
    PackageConfig config, Uri? baseUri, StringSink output) {
  // Can be optimized.
  var data = packageConfigToJson(config, baseUri);
  output.write(const JsonEncoder.withIndent('  ').convert(data));
}

Map<String, Object?> packageConfigToJson(PackageConfig config, Uri? baseUri) =>
    <String, Object?>{
      ...?_extractExtraData(config.extraData, _topNames),
      _configVersionKey: PackageConfig.maxVersion,
      _packagesKey: [
        for (var package in config.packages)
          <String, Object?>{
            _nameKey: package.name,
            _rootUriKey: trailingSlash((package.relativeRoot
                    ? relativizeUri(package.root, baseUri)
                    : package.root)
                .toString()),
            if (package.root != package.packageUriRoot)
              _packageUriKey: trailingSlash(
                  relativizeUri(package.packageUriRoot, package.root)
                      .toString()),
            if (package.languageVersion != null &&
                package.languageVersion is! InvalidLanguageVersion)
              _languageVersionKey: package.languageVersion.toString(),
            ...?_extractExtraData(package.extraData, _packageNames),
          }
      ],
    };

void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) {
  var extraData = config.extraData;
  // Write .packages too.
  String? comment;
  if (extraData is Map<String, Object?>) {
    var generator = extraData[_generatorKey];
    if (generator is String) {
      var generated = extraData[_generatedKey];
      var generatorVersion = extraData[_generatorVersionKey];
      comment = 'Generated by $generator'
          "${generatorVersion is String ? " $generatorVersion" : ""}"
          "${generated is String ? " on $generated" : ""}.";
    }
  }
  packages_file.write(output, config, baseUri: baseUri, comment: comment);
}

/// If "extraData" is a JSON map, then return it, otherwise return null.
///
/// If the value contains any of the [reservedNames] for the current context,
/// entries with that name in the extra data are dropped.
Map<String, Object?>? _extractExtraData(
    Object? data, Iterable<String> reservedNames) {
  if (data is Map<String, Object?>) {
    if (data.isEmpty) return null;
    for (var name in reservedNames) {
      if (data.containsKey(name)) {
        var filteredData = {
          for (var key in data.keys)
            if (!reservedNames.contains(key)) key: data[key]
        };
        if (filteredData.isEmpty) return null;
        for (var value in filteredData.values) {
          if (!_validateJson(value)) return null;
        }
        return filteredData;
      }
    }
    return data;
  }
  return null;
}

/// Checks that the object is a valid JSON-like data structure.
bool _validateJson(Object? object) {
  if (object == null || true == object || false == object) return true;
  if (object is num || object is String) return true;
  if (object is List<Object?>) {
    return object.every(_validateJson);
  }
  if (object is Map<String, Object?>) {
    return object.values.every(_validateJson);
  }
  return false;
}
