/**
 * Computes a CSS border property value for the given base color.
 *
 * @group style
 *
 * @param {list} $border ($v-border) - CSS border value which can contain any of the color keywords
 * @param {color} $color ($v-background-color) - the base color to which the color keywords are applied to
 * @param {color} $context (null) - context/surrounding color where the border is expected to appear. The color of the final border is the darker of the two parameters passed to this function.
 * @param {number} $strength (1) - adjustment for the border contrast
 *
 * @return {list} The input $border value with any color keyword replaced with the corresponding actual color
 */
@function valo-border($border: $v-border, $color: $v-background-color, $context: null, $strength: 1) {
  @if type-of($border) != list {
    @return $border;
  }

  @if $context {
    @if color-luminance($color) > color-luminance($context) {
      $color: $context;
    }
  }

  $ret: null;
  @each $part in $border {
    @if $part == v-tint or $part == v-shade or $part == v-tone {
      $part: $part 1;
    }
    @if type-of($part) == list {
      $adjust-type: first-string($part);
      $adjust-amount: first-number($part);

      $tint: blend-screen(rgba(#fff, $v-bevel-depth/100%*$adjust-amount*$strength), $color);
      $shade: blend-linearburn(rgba(#000, $v-bevel-depth/100%*$adjust-amount*$strength), $color);

      @if $adjust-type == v-tone {
        @if is-dark-color($color) {
          $color: $tint;
        } @else {
          $color: $shade;
        }
      } @else if $adjust-type == v-tint {
        $color: $tint;
      } @else if $adjust-type == v-shade {
        $color: $shade;
      }

      $ret: $ret $color;
    } @else {
      $ret: $ret $part;
    }
  }
  @return $ret;
}


/**
 * Similar to the valo-border function, but adjusts the top and bottom border colors to suit an element with a gradient background-color.
 *
 * @group style
 *
 * @param {list} $border ($v-border) - CSS border value which can contain any of the color keywords
 * @param {color} $color ($v-background-color) - the base color to which the color keywords are applied to
 * @param {color} $context (null) - context/surrounding color where the border is expected to appear. The color of the final border is the darker of the two parameters passed to this function.
 * @param {number} $strength (1) - adjustment for the border contrast
 * @param {list} $gradient ($v-gradient) - Valo specific gradient value. See the documentation for $v-gradient.
 */
@mixin valo-border-with-gradient($border: $v-border, $color: $v-background-color, $context: null, $strength: 1, $gradient: $v-gradient) {
  border: valo-border($border, $color, $context, $strength);

  // Adjust border colors for gradient
  @if $gradient {
    $color-stops: valo-gradient-color-stops($color, $gradient);
    $top: first(first($color-stops));
    $bottom: first(last($color-stops));
    border-top-color: first-color(valo-border($border, $top, $context, $strength));
    border-bottom-color: first-color(valo-border($border, $bottom, $context, $strength));
  }
}


/**
 * Computes a CSS box-shadow value according to the specified style parameters.
 *
 * @group style
 *
 * @param {list} $bevel (null) - box-shadow value according to $v-bevel documentation
 * @param {number} $bevel-depth ($v-bevel-depth) - percentage defining the depth/amount of the bevel effect. Affects the color keywords specified in the $bevel parameter.
 * @param {list} $shadow (null) - box-shadow value according to $v-shadow documentation
 * @param {number} $shadow-opacity ($v-shadow-opacity) - percentage defining the opacity/amount of the shadow effect. Affects the color keywords specified in the $shadow parameter.
 * @param {color} $background-color ($v-background-color) - the base color to which the color keywords are applied to
 * @param {list} $gradient (null) - Valo specific gradient value. See the documentation for $v-gradient. Affects the color keywords specified in the $bevel parameter.
 * @param {bool} $include-focus (false) - should the box-shadow value include $v-focus-style as well (only added if $v-focus-style is a)
 *
 * @return {list} CSS box-shadow value, combined from $bevel and $shadow with all occurences of v-tint, v-shade and v-tone color keywords replaced with the corresponding actual color
 */
@function valo-bevel-and-shadow ($bevel: null, $bevel-depth: $v-bevel-depth, $shadow: null, $shadow-opacity: $v-shadow-opacity, $background-color: $v-background-color, $gradient: null, $include-focus: false) {
  $box-shadow: null;

  @if $bevel {
    @if list-of-lists($bevel) {
      @each $b in $bevel {
        $this: valo-bevel-and-shadow($bevel: $b, $shadow: null, $background-color: $background-color, $gradient: $gradient);
        @if $this {
          @if length($box-shadow) > 0 {
            $box-shadow: $box-shadow, $this;
          } @else {
            $box-shadow: $this;
          }
        }
      }
    } @else if $bevel and $bevel != none {
      $this: valo-replace-tones($bevel, $background-color, $gradient);
      @if $this {
        @if length($box-shadow) > 0 {
          $box-shadow: $box-shadow, $this;
        } @else {
          $box-shadow: $this;
        }
      }
    }
  }

  @if $shadow {
    @if list-of-lists($shadow) {
      @each $s in $shadow {
        $this: valo-bevel-and-shadow($bevel: null, $shadow: $s, $background-color: null, $gradient: null);
        @if $this {
          @if length($box-shadow) > 0 {
            $box-shadow: $box-shadow, $this;
          } @else {
            $box-shadow: $this;
          }
        }
      }
    } @else {
      $this: valo-replace-shadow($shadow);
      @if $this {
        @if length($box-shadow) > 0 {
          $box-shadow: $box-shadow, $this;
        } @else {
          $box-shadow: $this;
        }
      }
    }
  }

  @if $include-focus and type-of($v-focus-style) == list {
    $box-shadow: $v-focus-style, $box-shadow;
  }

  @return $box-shadow;
}


/**
 * Replaces color keywords in the given list.
 *
 * @group style
 *
 * @param {list} $list - any CSS list with possible color keywords
 * @param {color} $color - The color to which color keywords are applied to
 * @param {list} $gradient (null) - Valo specific gradient value. See the documentation for $v-gradient. Affects the replacement colors to accommodate the gradient.
 *
 * @return {list} The input $list parameter with all occurences of v-tint, v-shade and v-tone color keywords replaced with the corresponding actual color
 */
@function valo-replace-tones($list, $color, $gradient: null) {
  $ret: ();

  @each $part in $list {
    @if $part == v-tint or $part == v-shade or $part == v-tone {
      $part: $part 1;
    }
    @if type-of($part) == list {
      $adjust-type: first-string($part);
      $adjust-amount: first-number($part);

      $top-color: $color;
      $bottom-color: $color;

      @if $gradient {
        $color-stops: valo-gradient-color-stops($color, $gradient);
        $top-color: first(first($color-stops));
        $bottom-color: first(last($color-stops));
      }

      $tint: blend-lighten(adjust-color($top-color, $lightness: $v-bevel-depth/4*$adjust-amount, $saturation: -$v-bevel-depth/2), scale-color($top-color, $lightness: $v-bevel-depth/4*$adjust-amount));
      $shade: blend-darken(rgba(scale-color($bottom-color, $lightness: max(-30%, -$v-bevel-depth/3*$adjust-amount), $saturation: -$v-bevel-depth/2), $v-bevel-depth/100%), $bottom-color);

      $new-color: null;
      @if $adjust-type == v-tone {
        @if is-dark-color($color) {
          $new-color: $tint;
        } @else {
          $new-color: $shade;
        }
      } @else if $adjust-type == v-tint {
        $new-color: $tint;
      } @else if $adjust-type == v-shade {
        $new-color: $shade;
      }

      $ret: join($ret, $new-color);

    } @else {
      $ret: join($ret, $part);
    }
  }

  @return $ret;
}


/**
 * Replace color keywords in the given box-shadow parameter.
 *
 * @group style
 *
 * @param {list} $shadow - CSS box-shadow value, or any other CSS list which might contain either the v-tint or the v-shade color keywords.
 *
 * @return {list} the input $shadow parameter with all occurences of v-tint and v-shade color keywords replaced with the corresponding actual color
 */
@function valo-replace-shadow ($shadow) {
  $ret: ();
  @each $part in $shadow {
    @if $part == v-tint or $part == v-shade {
      $part: $part 1;
    }
    @if type-of($part) == list {
      $adjust-type: first-string($part);
      $adjust-amount: first-number($part);

      $tint: rgba(#fff, min(1, $v-shadow-opacity/100% * $adjust-amount));
      $shade: rgba(#000, min(1, $v-shadow-opacity/100% * $adjust-amount));

      $color: null;
      @if $adjust-type == v-tint {
        $color: $tint;
      } @else if $adjust-type == v-shade {
        $color: $shade;
      }

      $ret: join($ret, $color);

    } @else {
      $ret: join($ret, $part);
    }
  }
  @return $ret;
}


/**
 * Return a CSS text-shadow property value according to the specified style parameters.
 *
 * @group style
 *
 * @param {color} $font-color ($v-font-color) - the color of the text to which the text-shadow is added
 * @param {color} $background-color ($v-background-color) - the color of the background where the text is to which the text-shadow is added
 * @param {size} $offset (-1px) - the size of the text shadow vertical offset
 * @param {number (pct)} $opacity ($v-shadow-opacity) - the percentage amount of shadow which is applied
 */
@function valo-text-shadow($font-color: $v-font-color, $background-color: $v-background-color, $offset: -1px, $opacity: $v-shadow-opacity) {
  $color: null;
  @if color-luminance($font-color) < color-luminance($background-color) {
    $color: rgba(#fff, $opacity / 100%);
    $offset: $offset * -1;
  } @else {
    $color: rgba(#000, $opacity / 100%);
  }

  @return 0 $offset 0 $color;
}
