@use 'sass:list';
@use 'sass:meta';

// Error Output Override
// ---------------------
/// Optionally turn off error output for testing,
/// with the 'catch-errors' setting
/// @access private
$catch-errors: false !default;


// Error [function]
// ----------------
/// Optionally return error messages without failing,
/// as a way to test error cases
///
/// @param {string} $message -
///   A useful error message, explaining the problem
/// @param {string} $source -
///   The original source of the error for debugging
/// @param {bool} $catch [$catch-errors] -
///   Optionally return the error rather than failing
/// @return {string} -
///   Combined error with source and message
/// @throws When `$catch == true`
/// @access private
@function error(
  $message,
  $source,
  $catch: $catch-errors
) {
  @if $catch {
    @return 'ERROR [#{$source}] #{$message}';
  }

  @error '[#{$source}] #{$message}';
}


@function type(
  $value,
  $expect,
  $source,
  $name
) {
  $type: meta.type-of($value);
  $pass: if(
    meta.type-of($expect) == 'list',
    list.index($expect, $type),
    $type == $expect
  );

  @if (not $pass) {
    @if (meta.type-of($expect) == 'list') {
      $expect: 'one of (#{list.join((), $expect, comma)})';
    } @else {
      $expect: 'a #{$expect}';
    }

    @return error(
      '$#{$name} must be #{$expect}, got #{$type}: #{$value}',
      $source
    );
  }

  @return false;
}


// Error [mixin]
// -------------
/// Optionally output mixin error messages without failing,
/// as a way to test error cases
///
/// @param {string} $message -
///   A useful error message, explaining the problem
/// @param {string} $source -
///   The original source of the error for debugging
/// @param {bool} $catch [$catch-errors] -
///   Optionally return the error rather than failing
/// @output -
///   `--accoutrement-error` property with error message
/// @access private
@mixin error(
  $message,
  $source,
  $catch: $catch-errors
) {
  --accoutrement-error: '#{error($message, $source, $catch)}';
}
