@charset 'UTF-8';

////
/// Flavor SCSS Mixins Background
/// @group mixins-background
/// @author blackmirror1980
////

@import 'background-color';
@import 'background-image';
@import 'background-position';
@import 'background-size';
@import 'background-repeat';
@import 'background-origin-clip';
@import 'background-attachment';

/// Background mixin
///
/// @example scss - Usage
///   .background-element {
///     @include background(null url('http://test.com/image.png') null cover no-repeat null null fixed);
///   }
///
/// @example css - Output
///   .background-element {
///     background-color: transparent;
///     background-image: url('http://test.com/image.png');
///     background-position: 0 0;
///     background-size: cover;
///     background-repeat: no-repeat;
///     background-origin: padding-box;
///     background-clip: border-box;
///     background-attachment: fixed;
///   }
/// @example scss - Usage Shorthand
///   .background-element {
///     @include background((
///       image: url('http://test.com/image.png'),
///       size: cover,
///       repeat: no-repeat,
///       attachment: fixed
///     ), true);
///   }
///
/// @example css - Output Shorthand
///   .background-element {
///     background: transparent url('http://test.com/image.png') 0 0/cover no-repeat padding-box border-box fixed;
///   }
/// @requires {function} extend
/// @requires {function} is-defined
/// @requires {function} is-background-origin-clip
/// @requires {function} nth-value
/// @access public
/// @param {object | map} $options - the background options
/// @param {color} $options.color [transparent] - background color
/// @param {image} $options.image [none] - background image
/// @param {string | array} $options.position [0 0] - background position
/// @param {string} $options.size [auto] - background size
/// @param {string} $options.repeat [repeat] - background repeat
/// @param {string} $options.origin [padding-box] - background origin
/// @param {string} $options.clip [border-box] - background clip
/// @param {string} $options.attachment [scroll] - background attachment
/// @param {boolean} $shorthand [false] - specifies if shorthand selector will be used or not
/// @param {boolean} $important [false] - if true, will render the important rule
@mixin background($options, $shorthand: false, $important: false) {
  @if is-css-default($options) {
    background: $options important($important);
  }
  @else {
    $settings: (color: transparent, image: none, position: 0 0, size: auto, repeat: repeat, origin: padding-box, clip: border-box, attachment: scroll);

    @if is-object($options) {
      $settings: extend($settings, $options);
    }
    @else {
      $color: nth-value($options, 1);

      @if is-defined($color) {
        $settings: extend($settings, (color: $color));
      }

      $image: nth-value($options, 2);

      @if is-defined($image) {
        $settings: extend($settings, (image: $image));
      }

      $position: nth-value($options, 3);

      @if is-defined($position) {
        $settings: extend($settings, (position: $position));
      }

      $size: nth-value($options, 4);

      @if is-defined($size) {
        $settings: extend($settings, (size: $size));
      }

      $repeat: nth-value($options, 5);

      @if is-defined($repeat) {
        $settings: extend($settings, (repeat: $repeat));
      }

      $origin: nth-value($options, 6);

      @if is-defined($origin) {
        $settings: extend($settings, (origin: $origin));
      }

      $clip: nth-value($options, 7);

      @if is-defined($clip) {
        $settings: extend($settings, (clip: $clip));
      }

      $attachment: nth-value($options, 8);

      @if is-defined($attachment) {
        $settings: extend($settings, (attachment: $attachment));
      }
    }

    $background: ();

    $background-color: map-get($settings, color);

    @if is-css-color($background-color) {
      @if $shorthand == true {
        $background: append($background, $background-color);
      }
      @else {
        @include background-color($background-color, $important);
      }
    }
    @else {
      @warn '`background-color: #{$background-color}` is not a valid css color';
    }

    $background-image: map-get($settings, image);

    @if is-background-image($background-image) {
      @if not is-background-image-mode($background-image) {
        $background-image: inspect-url($background-image);
      }

      @if $shorthand == true {
        $background: append($background, $background-image);
      }
      @else {
        @include background-image($background-image, $important);
      }
    }
    @else {
      @warn '`background-image: #{$background-image}` is not a valid background-image value';
    }

    $background-position: map-get($settings, position);
    $background-size: map-get($settings, size);

    @if is-background-position($background-position) and is-background-size($background-size) {
      @if $shorthand == true {
        $background: append($background, $background-position + '/' + $background-size);
      }
      @else {
        @include background-position($background-position, $important);
        @include background-size($background-size, $important);
      }
    }
    @else {
      @warn '`background-position: #{$background-position}` is not a valid background-position value';
      @warn '`background-size: #{$background-size}` is not a valid background-size value';
    }

    $background-repeat: map-get($settings, repeat);

    @if is-background-repeat($background-repeat) {
      @if $shorthand == true {
        $background: append($background, $background-repeat);
      }
      @else {
        @include background-repeat($background-repeat, $important);
      }
    }
    @else {
      @warn '`background-repeat: #{$background-repeat}` is not a valid background-repeat value';
    }

    $background-origin: map-get($settings, origin);

    @if is-background-origin-clip($background-origin) {
      @if $shorthand == true {
        $background: append($background, $background-origin);
      }
      @else {
        @include background-origin($background-origin, $important);
      }
    }
    @else {
      @warn '`background-origin: #{$background-origin}` is not a valid background-origin value';
    }

    $background-clip: map-get($settings, clip);

    @if is-background-origin-clip($background-clip) {
      @if $shorthand == true {
        $background: append($background, $background-clip);
      }
      @else {
        @include background-clip($background-clip, $important);
      }
    }
    @else {
      @warn '`background-clip: #{$background-clip}` is not a valid background-clip value';
    }

    $background-attachment: map-get($settings, attachment);

    @if is-background-attachment($background-attachment) {
      @if $shorthand == true {
        $background: append($background, $background-attachment);
      }
      @else {
        @include background-attachment($background-attachment, $important);
      }
    }
    @else {
      @warn '`background-attachment: #{$background-attachment}` is not a valid background-attachment value';
    }

    @if $shorthand == true {
      background: $background important($important);
    }
  }
}

@function is-gradient-color-stop($color-stop) {
  @if list-separator($color-stop) == space {
    $color: nth-value($color-stop, 1);

    @if length($color-stop) > 1 {
      $stop: nth-value($color-stop, 2);

      @return is-color($color) and (is-relative-length($stop) or is-absolute-length($stop));
    }
    @else {
      @return is-color($color);
    }
  }

  @return is-color($color-stop);
}

@function is-gradient-color-stops($color-stops...) {
  @if list-separator($color-stops) == comma {
    $is-valid: true;

    @each $color-stop in $color-stops {
      @if $is-valid {
        $is-valid: is-gradient-color-stop($color-stop);
      }
    }

    @return $is-valid;
  }

  @return false;
}

$linear-gradient-directions: (to top, to top right, to right top, to right, to bottom right, to right bottom, to bottom, to bottom left, to left bottom, to left, to left top, to top left);

@function is-linear-gradient-direction($gdir) {
  @return is-defined($gdir) and array-contains($linear-gradient-directions, $gdir);
}

@function is-linear-gradient-definition($gdef) {
  @return is-defined($gdef) and (is-linear-gradient-direction($gdef) or is-angle($gdef));
}

@function is-linear-gradient-options($options...) {
  @if list-separator($options) == comma {
    $definition: array-head($options);
    $color-stops: $options;

    @if is-linear-gradient-definition($definition) {
      $color-stops: array-tail($options);
    }
    @else {
      $definition: to bottom;
    }

    @return is-linear-gradient-definition($definition) and is-gradient-color-stops($color-stops...);
  }

  @return false;
}

@mixin linear-gradient-base($function: linear-gradient, $options...) {
  @if is-linear-gradient-options($options...) {
    $definition: array-head($options);
    $color-stops: $options;

    @if is-linear-gradient-definition($definition) {
      $color-stops: array-tail($options);
    }
    @else {
      $definition: to bottom;
    }

    $linear-gradient-function-call: $function + '(' + $definition + ',' + $color-stops + ')';

    background-image: #{$linear-gradient-function-call};
  }
}

@mixin linear-gradient($options...) {
  @include linear-gradient-base(linear-gradient, $options...);
}

@mixin repeating-linear-gradient($options...) {
  @include linear-gradient-base(repeating-linear-gradient, $options...);
}

@function is-radial-gradient-size($gp) {
  @return is-background-position($gp);
}

$radial-gradient-shapes: (circle, ellipse);

@function is-radial-gradient-shape($gs) {
  @return is-defined($gs) and array-contains($radial-gradient-shapes, $gs);
}

$radial-gradient-extent-keywords: (closest-side, closest-corner, farthest-side, farthest-corner, cover, contain);

@function is-radial-gradient-extent-keyword($gek) {
  @return is-defined($gek) and array-contains($radial-gradient-extent-keywords, $gek);
}

@function is-radial-gradient-position($gp) {
  @return is-background-position($gp);
}

@function get-radial-gradient-definition($gd) {
  $gradient-definition-split: string-split(inspect($gd), ' at ');
  $gradient-definition: string-split(nth-value($gradient-definition-split, 1), ' ');
  $gradient-position: center;

  @if length($gradient-definition-split) > 1 {
    $gradient-position: string-split(nth-value($gradient-definition-split, 2), ' ');
  }

  // $gradient-shape-width: null;
  // $gradient-shape-height: null;
  $gradient-shape: ellipse;
  $gradient-extend-keyword: farthest-corner;

  @each $gradient-definition-item in $gradient-definition {
    $gradient-definition-item-index: index($gradient-definition, $gradient-definition-item);

    // @if is-number-between($gradient-definition-item-index, 1, 2) {
    //   $gradient-definition-item-number: to-number($gradient-definition-item);
    //   @if is-relative-length($gradient-definition-item-number) or is-absolute-length($gradient-definition-item-number) {
    //     @if $gradient-definition-item-index = 1 {
    //       $gradient-shape-width: $gradient-definition-item-number;
    //     }

    //     @if $gradient-definition-item-index = 2 {
    //       $gradient-shape-height: $gradient-definition-item-number;
    //     }
    //   }
    // }

    @if is-radial-gradient-shape($gradient-definition-item) {
      $gradient-shape: $gradient-definition-item;
    }
    @else if is-radial-gradient-extent-keyword($gradient-definition-item) {
      $gradient-extend-keyword: $gradient-definition-item;
    }
  }

  // @if is-defined($gradient-shape-width) and is-null($gradient-shape-height) {
  //   $gradient-shape-height: $gradient-shape-width;
  // }

  @if not is-radial-gradient-position($gradient-position) {
    $gradient-position: center;
  }

  $radial-gradient-definition: (
    shape: $gradient-shape,
    extent-keyword: $gradient-extend-keyword,
    position: $gradient-position
  );

  // @if is-defined($gradient-shape-width) and is-defined($gradient-shape-height) {
  //   $radial-gradient-definition: extend($radial-gradient-definition, (
  //     size: $gradient-shape-width $gradient-shape-height
  //   ));
  // }

  @return $radial-gradient-definition;
}

@function is-radial-gradient-definition($gd) {
  $gradient-definition-valid: false;

  @if list-separator($gd) == space {
    // $gradient-definition-size: get($gd, 'size');
    $gradient-definition-shape: get($gd, 'shape');
    $gradient-definition-extent-keyword: get($gd, 'extent-keyword');
    $gradient-definition-position: get($gd, 'position');

    $gradient-definition-valid: true;

    // @if is-defined($gradient-definition-size) {
    //   $gradient-definition-valid: is-radial-gradient-size($gradient-definition-size);
    // }

    // @if $gradient-definition-valid and is-defined($gradient-definition-shape) {
    @if is-defined($gradient-definition-shape) {
      $gradient-definition-valid: is-radial-gradient-shape($gradient-definition-shape);
    }

    @if $gradient-definition-valid and is-defined($gradient-definition-extent-keyword) {
      $gradient-definition-valid: is-radial-gradient-extent-keyword($gradient-definition-extent-keyword);
    }

    @if $gradient-definition-valid and is-defined($gradient-definition-position) {
      $gradient-definition-valid: is-radial-gradient-position($gradient-definition-position);
    }
  }

  @return $gradient-definition-valid;
}

@function is-radial-gradient-options($options...) {
  @if list-separator($options) == comma {
    $definition: array-head($options);
    $color-stops: $options;

    @if not is-gradient-color-stop($definition) {
      $color-stops: array-tail($options);
    }
    @else {
      $definition: ellipse farthest-corner at center;
    }

    $definition: get-radial-gradient-definition($definition);

    @return is-radial-gradient-definition($definition) and is-gradient-color-stops($color-stops...);
  }

  @return false;
}

@mixin radial-gradient-base($function: radial-gradient, $options...) {
  @if is-radial-gradient-options($options...) {
    $definition: array-head($options);
    $color-stops: $options;

    @if not is-gradient-color-stop($definition) {
      $color-stops: array-tail($options);
    }
    @else {
      $definition: ellipse farthest-corner at center;
    }

    $definition: get-radial-gradient-definition($definition);

    $radial-gradient-definition: '';

    // $radial-gradient-definition-size: get($definition, 'size');

    $radial-gradient-definition-shape: get($definition, 'shape');
    $radial-gradient-definition-extent-keyword: get($definition, 'extent-keyword');
    $radial-gradient-definition-position: get($definition, 'position');

    // @if is-defined($radial-gradient-definition-size) {
    //   $radial-gradient-definition: $radial-gradient-definition-size;
    // }

    @if is-defined($radial-gradient-definition-shape) {
      $radial-gradient-definition: $radial-gradient-definition-shape;
    }

    @if is-defined($radial-gradient-definition-extent-keyword) {
      $radial-gradient-definition: $radial-gradient-definition + ' ' + $radial-gradient-definition-extent-keyword;
    }

    @if is-defined($radial-gradient-definition-position) {
      $radial-gradient-definition: $radial-gradient-definition + ' at ' + $radial-gradient-definition-position;
    }

    $radial-gradient-function-call: $function + '(' + $radial-gradient-definition + ',' + $color-stops + ')';

    background-image: #{$radial-gradient-function-call};
  }
}

@mixin radial-gradient($options...) {
  @include radial-gradient-base(radial-gradient, $options...);
}

@mixin repeating-radial-gradient($options...) {
  @include radial-gradient-base(repeating-radial-gradient, $options...);
}
