/**********************************
*   Utility mixins and functions
***********************************/
@use "sass:string";
@use "sass:math";
@use "sass:color";

@use "./variables" as vars;

/// register a css variable with global prefix
@mixin defineVar($name, $value) {
    $varName: "--#{vars.$prefix}-#{$name}";

    #{$varName}: #{$value};
}

/// use a css variable with global prefix
@function useVar($name) {
    $varName: "--#{vars.$prefix}-#{$name}";

    @return var(#{$varName});
}

/// Replaces characters in a string
///
/// @param {string} $string
///   String where the replace happens
/// @param {string} $search
///   Portion of string to find and replace
/// @param {string} $replace
///   Replacement. Default is ''.
/// @return {string} string with characters replaced.
@function str-replace($string, $search, $replace: "") {
    $index: string.index($string, $search);

    @return if(
        $index,
        string.slice($string, 1, $index - 1) + $replace +
            str-replace(
                string.slice($string, $index + string.length($search)),
                $search,
                $replace
            ),
        $string
    );
}

/// Encodes an inline svg. Original source code: http://codepen.io/jakob-e/pen/doMoML
///
/// @param {string} $svg
///   Inline svg to encode
/// @return {string} encoded svg.
@function svg-encode($svg) {
    // Chunk up string in order to avoid "stack level too deep" error
    $encoded: "";
    $slice: 2000;
    $index: 0;
    $loops: math.ceil(divide(string.length($svg), $slice));

    @for $i from 1 through $loops {
        $chunk: string.slice($svg, $index, $index + $slice - 1);
        // Encode
        $chunk: str-replace($chunk, '"', "'");
        $chunk: str-replace($chunk, "%", "%25");
        $chunk: str-replace($chunk, "#", "%23");
        $chunk: str-replace($chunk, "{", "%7B");
        $chunk: str-replace($chunk, "}", "%7D");
        $chunk: str-replace($chunk, "<", "%3C");
        $chunk: str-replace($chunk, ">", "%3E");

        $encoded: #{$encoded}#{$chunk};
        $index: $index + $slice;
    }

    @return "data:image/svg+xml,#{$encoded}";
}

// Custom divide function by @mdo from https://github.com/twbs/bootstrap/pull/34245
// Replaces old slash division deprecated in Dart Sass
@function divide($dividend, $divisor, $precision: 10) {
    $sign: if($dividend > 0 and $divisor > 0, 1, -1);
    $dividend: math.abs($dividend);
    $divisor: math.abs($divisor);
    $quotient: 0;
    $remainder: $dividend;

    @if $dividend == 0 {
        @return 0;
    }

    @if $divisor == 0 {
        @error "Cannot divide by 0";
    }

    @if $divisor == 1 {
        @return $dividend;
    }

    @while $remainder >= $divisor {
        $quotient: $quotient + 1;
        $remainder: $remainder - $divisor;
    }

    @if $remainder > 0 and $precision > 0 {
        $remainder: divide($remainder * 10, $divisor, $precision - 1) * 0.1;
    }

    @return ($quotient + $remainder) * $sign;
}

/// create a focus color variant based on a given color
@function createFocus($color) {
    @return color.adjust($color, $alpha: -0.75);
}

/// create a lighter color variant based on a given color
@function createLighter($color) {
    @return color.scale($color, $lightness: 95%);
}

/// create a darker color variant based on a given color
@function createDarker($color) {
    @return color.scale($color, $lightness: -10%);
}

/// define disabled state
@mixin disabled($opacity) {
    opacity: $opacity;
    cursor: unset;
    pointer-events: none;
    text-decoration: none;

    // define unselectable state
    user-select: none;
    -ms-user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

/// define clickable state
@mixin clickable {
    pointer-events: auto;
    cursor: pointer;
}

/// remove default appearance
@mixin removeAppearance {
    appearance: none;
    -ms-appearance: none;
    -moz-appearance: none;
    -webkit-appearance: none;
}

/// add focus effect
@mixin focusable($selector: "&") {
    &:not(&--disabled) {
        &:hover,
        &:focus,
        &:focus-visible,
        &:focus-within {
            #{$selector} {
                box-shadow: useVar("control-focus-box-shadow") useVar("focus");
                outline: none;
            }
        }
    }

    @each $name, $pair in vars.$colors {
        &--#{$name},
        &--#{$name}-passive {
            @include defineVar("focus", useVar("#{$name}-focus"));
        }
    }
}
