/// Validation
/// ==========
/// Each argument to Su has a single canonical syntax.
/// These validation functions check to ensure
/// that each argument is valid,
/// in order to provide useful errors
/// before attempting to calculate the results/
///
/// @group x-validation
///
/// @see su-valid-columns
/// @see su-valid-gutters
/// @see su-valid-spread
/// @see su-valid-location



// Valid Span
// ----------
/// Check that the `span` argument
/// is a number, length, or column-list
///
/// @group x-validation
///
/// @param {number | list} $span -
///   Number of columns, or length of span
///
/// @return {number | list} -
///   Validated `$span` number, length, or columns list
///
/// @throw
///   when span value is not a number, or valid column list
@function su-valid-span(
  $span
) {
  $type: type-of($span);
  @if ($type == 'number') {
    @return $span;
  } @else if ($type == 'list') and su-valid-columns($span, 'silent-failure') {
    @return $span;
  }

  $actual: '[#{type-of($span)}] `#{inspect($span)}`';
  @return _susy-error(
    '#{$actual} is not a valid number, length, or column-list for $span.',
    'su-valid-span');
}



// Valid Columns
// -------------
/// Check that the `columns` argument is a valid
/// list of column-lengths
///
/// @group x-validation
///
/// @param {list} $columns -
///   List of column-lengths
/// @param {bool} $silent-failure [true] -
///   Set false to return null on failure
///
/// @return {list} -
///   Validated `$columns` list
///
/// @throw
///   when column value is not a valid list of numbers
@function su-valid-columns(
  $columns,
  $silent-failure: false
) {
  @if (type-of($columns) == 'list') {
    $fail: false;

    @each $col in $columns {
      @if (type-of($col) != 'number') {
        $fail: true;
      }
    }

    @if not $fail {
      @return $columns;
    }
  }

  // Silent Failure
  @if $silent-failure {
    @return null;
  }

  // Error Message
  $actual: '[#{type-of($columns)}] `#{inspect($columns)}`';

  @return _susy-error(
    '#{$actual} is not a valid list of numbers for $columns.',
    'su-valid-columns');
}



// Valid Gutters
// -------------
/// Check that the `gutters` argument is a valid number
///
/// @group x-validation
///
/// @param {number} $gutters -
///   Width of a gutter
///
/// @return {number} -
///   Validated `$gutters` number
///
/// @throw
///   when gutter value is not a number
@function su-valid-gutters(
  $gutters
) {
  $type: type-of($gutters);

  @if ($type == 'number') {
    @return $gutters;
  }

  $actual: '[#{$type}] `#{inspect($gutters)}`';
  @return _susy-error(
    '#{$actual} is not a number or length for $gutters.',
    'su-valid-gutters');
}



// Valid Spread
// ------------
/// Check that the `spread` argument is a valid
/// intiger between `-1` and `1`
///
/// @group x-validation
///
/// @param {0 | 1 | -1} $spread -
///   Number of gutters to include in a span,
///   relative to the number columns
///
/// @return {0 | 1 | -1} -
///   Validated `$spread` number
///
/// @throw
///   when spread value is not a valid spread
@function su-valid-spread(
  $spread
) {
  @if index(0 1 -1, $spread) {
    @return $spread;
  }

  $actual: '[#{type-of($spread)}] `#{inspect($spread)}`';
  @return _susy-error(
    '#{$actual} is not a normalized [0 | 1 | -1] value for `$spread`.',
    'su-valid-spread');
}



// Valid Location
// --------------
/// Check that the `location` argument is a valid number,
/// within the scope of available columns
///
/// @group x-validation
///
/// @param {number} $span -
///   Number of grid-columns to be spanned
/// @param {integer | string} $location -
///   Starting (1-indexed) column-position of that span
/// @param {list} $columns -
///   List of available columns in the grid
///
/// @return {integer} -
///   Validated `$location` intiger
///
/// @throw
///   when location value is not a valid index,
///   given the context and span.
@function su-valid-location(
  $span,
  $location,
  $columns
) {
  $count: length($columns);

  @if $location {
    @if (type-of($location) != 'number') or (not unitless($location)) {
      $actual: '[#{type-of($location)}] `#{$location}`';
      @return _susy-error(
        '#{$actual} is not a unitless number for $location.',
        'su-valid-location');
    } @else if (round($location) != $location) {
      @return _susy-error(
        'Location (`#{$location}`) must be a 1-indexed intiger position.',
        'su-valid-location');
    } @else if ($location > $count) or ($location < 1) {
      @return _susy-error(
        'Position `#{$location}` does not exist in grid `#{$columns}`.',
        'su-valid-location');
    } @else if ($location + $span - 1 > $count) {
      $details: 'grid `#{$columns}` for span `#{$span}` at `#{$location}`';
      @return _susy-error(
        'There are not enough columns in #{$details}.',
        'su-valid-location');
    }
  }

  @return $location;
}
