// Copyright 2019 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import '../../exception.dart';
import '../../importer.dart';
import '../../importer/utils.dart';
import '../../util/span.dart';
import '../embedded_sass.pb.dart' hide SourceSpan;
import '../utils.dart';
import 'base.dart';

/// An importer that asks the host to resolve imports.
final class HostImporter extends ImporterBase {
  /// The host-provided ID of the importer to invoke.
  final int _importerId;

  /// The set of URL schemes that this importer promises never to return from
  /// [canonicalize].
  final Set<String> _nonCanonicalSchemes;

  HostImporter(
    super.dispatcher,
    this._importerId,
    Iterable<String> nonCanonicalSchemes,
  ) : _nonCanonicalSchemes = Set.unmodifiable(nonCanonicalSchemes) {
    for (var scheme in _nonCanonicalSchemes) {
      if (isValidUrlScheme(scheme)) continue;
      throw SassException(
        '"$scheme" isn\'t a valid URL scheme (for example "file").',
        bogusSpan,
      );
    }
  }

  Uri? canonicalize(Uri url) {
    var request = OutboundMessage_CanonicalizeRequest()
      ..importerId = _importerId
      ..url = url.toString()
      ..fromImport = fromImport;
    if (canonicalizeContext.containingUrlWithoutMarking
        case var containingUrl?) {
      request.containingUrl = containingUrl.toString();
    }
    var response = dispatcher.sendCanonicalizeRequest(request);
    if (!response.containingUrlUnused) canonicalizeContext.containingUrl;

    return switch (response.whichResult()) {
      InboundMessage_CanonicalizeResponse_Result.url => parseAbsoluteUrl(
          "The importer",
          response.url,
        ),
      InboundMessage_CanonicalizeResponse_Result.error => throw response.error,
      InboundMessage_CanonicalizeResponse_Result.notSet => null,
    };
  }

  ImporterResult? load(Uri url) {
    var response = dispatcher.sendImportRequest(
      OutboundMessage_ImportRequest()
        ..importerId = _importerId
        ..url = url.toString(),
    );

    return switch (response.whichResult()) {
      InboundMessage_ImportResponse_Result.success => ImporterResult(
          response.success.contents,
          sourceMapUrl: response.success.sourceMapUrl.isEmpty
              ? null
              : parseAbsoluteUrl(
                  "The importer",
                  response.success.sourceMapUrl,
                ),
          syntax: syntaxToSyntax(response.success.syntax),
        ),
      InboundMessage_ImportResponse_Result.error => throw response.error,
      InboundMessage_ImportResponse_Result.notSet => null,
    };
  }

  bool isNonCanonicalScheme(String scheme) =>
      _nonCanonicalSchemes.contains(scheme);

  String toString() => "HostImporter";
}
