// =============================================================================
// TOOLS / #GRADIENTS
// =============================================================================

// Functions (Private / Framework Only)
// ==============================================

// _gradient-color-stops()
// ------------------------------------

// Function to return the gradient color points in a format usable by
// `linear-gradient` and other gradient mixins.
//
// `_gradient-color-stops()` takes two arguments:
//   - $key - The gradient key i.e. `sky-arts`
//   - $modifier - To reverse the gradient direction set this to 'invert'
//
// Example output:
// `_gradient-color-stops(sky-cinema)` = `#903 0%, #cb0033 100%`
// `_gradient-color-stops(sky-cinema, reverse)` = `#cb0033 0%, #903 100%`
//
@function _gradient-color-stops($key, $modifier: null) {
  @if map-has-key($gradients, $key) {
    $gradient: map-get($gradients, $key);
    // Create blank list to store color points
    $gradient-color-stops: null;

    // If specified, reverse the order of the gradient color stops
    @if $modifier == reverse {
      $gradient-reversed: reverse($gradient);

      @each $position, $value in $gradient-reversed {
        // Invert percentages i.e. 6% => 94%
        $reversed-position: 100% - $position;
        // Append ordered values to stop list
        $gradient-color-stops: append($gradient-color-stops, ($value $reversed-position), comma);
      }
    } @else {
      // By default, append a list of color stops for each percentage key.
      @each $position, $value in $gradient {
        $gradient-color-stops: append($gradient-color-stops, ($value $position), comma);
      }
    }

    @return $gradient-color-stops;
  }

  @warn "Unknown `#{$key}` in $gradients.";
  @return null;
}

// _gradient-fallback()
// ------------------------------------

// Function to automate selecting a fallback value for our gradient mixins,
// handling the logic of selecting a value if a valid colour is not supplied.
//
// `_gradient-fallback()` takes two arguments:
//   - $key - The gradient key i.e. `sky-arts`
//   - $fallback - The supplied fallback color to check
//
@function _gradient-fallback($key, $fallback:null) {
  // Set default fallback value
  $fallback-default: gradient-color($key, end);

  @if not $fallback {
    $fallback: $fallback-default;
  } @else if type-of($fallback) != color {
    @warn "#{$fallback} is not a valid color, falling back to last color in gradient";
    $fallback: $fallback-default;
  }

  @return $fallback;
}

// Functions
// ==============================================

// gradient-color()
// ------------------------------------

// Function to get gradient colors from `$gradients` instead of using `map-get`.
//
// Options:
// - key: Name of gradient (see toolkit-core/settings/colors)
// - color-stop:
//    - `×%` specific percentage value
//    - `start` the first defined percentage value
//    - `end` the last defined percentage value
//
// See `docs/` for usage.
@function gradient-color($key, $color-stop: end) {
  @if map-has-key($gradients, $key) {
    // Store the available color stop keys (e.g. 0%, 50%, 100%)
    $color-stop-keys: map-keys(map-get($gradients, $key));
    $color-stop-keys-length: length($color-stop-keys);

    // If the `start` color stop is specified, select the first available key.
    @if $color-stop == start {
      $color-stop: nth($color-stop-keys, 1);
    }

    // If the `end` color stop is specified, select the last available key.
    @if $color-stop == end {
      $color-stop: nth($color-stop-keys, $color-stop-keys-length);
    }

    @if map-has-key(map-get($gradients, $key), $color-stop) {
      @return map-get(map-get($gradients, $key), $color-stop);
    }

    @warn "Unknown #{$color-stop} stop of `#{$key}` in $gradients.";
    @return null;
  }

  @warn "Unknown `#{$key}` in $gradients.";
  @return null;
}

// Mixins
// ===========================================

// @include gradient-background()
// ------------------------------------

// Mixin to generate complete background gradients. Uses values from our
// `$gradients` map in `settings/colors`.
//
// OPTIONS
// - key: Name of gradient
// - direction:
//    - "vertical" top to bottom gradient
//    - "vertical-invert" bottom to top gradient
//    - "horizontal" left to right gradient
//    - "radial" center to edge gradient
//
// See `docs/` for usage.
@mixin gradient-background($key, $direction:"vertical", $fallback: null) {
  @if map-has-key($gradients, $key) {

    $gradient-color-stops: _gradient-color-stops($key);

    @if map-has-key($gradient-directions, $direction) {
      // Fetch the direction map settings and assign to variables.
      $direction-legacy: map-get-deep($gradient-directions, $direction, legacy);
      $direction-standard: map-get-deep($gradient-directions, $direction, standard);
      $direction-type: map-get-deep($gradient-directions, $direction, type);
      $direction-reverse: map-get-deep($gradient-directions, $direction, reverse);

      // Reverse our gradient color stops for specified directions.
      @if ($direction-reverse == true) {
        $gradient-color-stops: _gradient-color-stops($key, reverse);
      }

      // Define our fallback background-color
      $fallback: _gradient-fallback($key, $fallback);

      // Output fallback background color + gradient with appropriate prefixes.
      background-color: $fallback;
      background-image: -webkit-#{$direction-type}-gradient(#{$direction-legacy}, $gradient-color-stops);
      background-image: -moz-#{$direction-type}-gradient(#{$direction-legacy}, $gradient-color-stops);
      background-image: -o-#{$direction-type}-gradient(#{$direction-legacy}, $gradient-color-stops);
      background-image: #{$direction-type}-gradient(#{$direction-standard}, $gradient-color-stops);
    } @else {
      @warn "`#{$direction}` is not a valid direction, see toolkit-core/tools/gradients for available options.";
    }
  } @else {
    @warn "Unknown `#{$key}` in $gradients.";
  }
}

// @include gradient-text()
// ------------------------------------

// Mixin to generate a text gradient styling.
//
// OPTIONS
// - key: Name of gradient (see toolkit-core/settings/_colors.scss)
// - direction:
//    - "vertical" top to bottom gradient
//    - "vertical-invert" bottom to top gradient
//    - "horizontal" left to right gradient
//    - "radial" center to edge gradient
//
// See `docs/` for usage.
@mixin gradient-text($key, $direction: horizontal, $fallback: null) {
  @if map-has-key($gradients, $key) {
    @if map-has-key($gradient-directions, $direction) {
      // Fetch the direction map settings and assign to variables.
      $direction-legacy: map-get(map-get($gradient-directions, $direction), legacy);
      $direction-type: map-get(map-get($gradient-directions, $direction), type);
      $direction-reverse: map-get(map-get($gradient-directions, $direction), reverse);

      // Fetch a list of the gradient's color stops from `$gradients`.
      $gradient-color-stops: _gradient-color-stops($key);

      // Reverse our gradient color stops for specified directions.
      @if ($direction-reverse == true) {
        $gradient-color-stops: _gradient-color-stops($key, reverse);
      }

      // Define our fallback background-color
      $fallback: _gradient-fallback($key, $fallback);

      /*! autoprefixer: off */
      /* stylelint-disable property-no-vendor-prefix, value-no-vendor-prefix */

      // Vendor prefix required as other browsers lack support.
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      // Ensure that the gradient finishes flush with the text and not with the
      // element’s natural bounding box.
      display: inline-block;
      // Fallback color for unsupported browsers.
      color: $fallback;
      background-image: -webkit-#{$direction-type}-gradient(#{$direction-legacy}, $gradient-color-stops);
      background-size: 100%;
      /* stylelint-enable */
    } @else {
      @warn "`#{$direction}` is not a valid direction, see toolkit-core/tools/gradients for available options.";
    }
  } @else {
    @warn "Unknown `#{$key}` in $gradients.";
  }
}
