// ============================================================================
// move.gl | Text Loader Mixins
// ============================================================================
// Copyright 2025 Scape Agency BV
// Licensed under MIT License
// ============================================================================

////
/// Text Loader Mixins
/// ===========================================================================
///
/// This module provides mixins for text-based loading animations.
///
/// @group Loaders
/// @author Scape Agency
/// @link https://move.gl
/// @since 0.1.0
/// @access public
////

@use "../../variables" as *;


// ============================================================================
// Keyframes
// ============================================================================

///
/// Text clip fill animation keyframes.
///
@mixin keyframes_text_fill {
    @keyframes text-fill {
        0% { clip-path: polygon(0 0, 0 0, 0 100%, 0 100%); }
        100% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
    }
}

///
/// Text bounce animation keyframes.
///
@mixin keyframes_text_bounce {
    @keyframes text-bounce {
        0%, 80%, 100% { transform: translateY(0); }
        40% { transform: translateY(-10px); }
    }
}

///
/// Text dot flash animation keyframes.
///
@mixin keyframes_text_dots {
    @keyframes text-dots {
        0% { content: ''; }
        25% { content: '.'; }
        50% { content: '..'; }
        75% { content: '...'; }
    }
}

///
/// Text letter fade animation keyframes.
///
@mixin keyframes_text_letter_fade {
    @keyframes text-letter-fade {
        0%, 100% { opacity: 0.3; }
        50% { opacity: 1; }
    }
}

///
/// Text scale pulse animation keyframes.
///
@mixin keyframes_text_pulse {
    @keyframes text-pulse {
        0%, 100% { transform: scale(1); opacity: 1; }
        50% { transform: scale(1.1); opacity: 0.7; }
    }
}

///
/// Text spotlight effect keyframes.
///
@mixin keyframes_text_spotlight {
    @keyframes text-spotlight {
        0% { background-position: -200% center; }
        100% { background-position: 200% center; }
    }
}

///
/// Text typing cursor blink keyframes.
///
@mixin keyframes_text_cursor {
    @keyframes text-cursor {
        0%, 100% { opacity: 0; }
        50% { opacity: 1; }
    }
}

///
/// Text wave animation keyframes.
///
@mixin keyframes_text_wave {
    @keyframes text-wave {
        0%, 100% { transform: translateY(0); }
        50% { transform: translateY(-20%); }
    }
}

///
/// Text shake animation keyframes.
///
@mixin keyframes_text_shake {
    @keyframes text-shake {
        0%, 100% { transform: translateX(0); }
        10%, 30%, 50%, 70%, 90% { transform: translateX(-2px); }
        20%, 40%, 60%, 80% { transform: translateX(2px); }
    }
}


// ============================================================================
// Text Loader Mixins
// ============================================================================

///
/// Text fill loader with clip-path animation.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color [#FFF] - Text color.
/// @param {Color} $fill-color [#FF3D00] - Fill color.
/// @param {Length} $size [2rem] - Font size.
/// @param {Time} $duration [2s] - Animation duration.
///
@mixin loader_text_fill(
    $text: 'Loading',
    $color: rgba(255, 255, 255, 0.3),
    $fill-color: $loader-color,
    $size: 2rem,
    $duration: 2s
) {
    position: relative;
    font-size: $size;
    font-weight: 700;
    color: var(--loader-bg, $color);

    &::after {
        content: attr(data-text);
        position: absolute;
        left: 0;
        top: 0;
        color: var(--loader-color, $fill-color);
        clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
        animation: text-fill $duration ease-in-out infinite;
    }
}

///
/// Text with animated dots loader.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [1.5s] - Animation duration.
///
@mixin loader_text_dots(
    $text: 'Loading',
    $color: $loader-color,
    $size: 1.5rem,
    $duration: 1.5s
) {
    font-size: $size;
    font-weight: 500;
    color: var(--loader-color, $color);

    &::after {
        content: '';
        animation: text-dots $duration steps(4) infinite;
    }
}

///
/// Bouncing letters loader.
///
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [1s] - Animation duration.
///
@mixin loader_text_bounce(
    $color: $loader-color,
    $size: 1.5rem,
    $duration: $loader-speed
) {
    display: inline-flex;
    gap: 0.1em;
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);

    span {
        display: inline-block;
        animation: text-bounce $duration ease-in-out infinite;

        @for $i from 1 through 10 {
            &:nth-child(#{$i}) {
                animation-delay: calc(($i - 1) * 0.1s);
            }
        }
    }
}

///
/// Fading letters loader.
///
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [1.5s] - Animation duration.
///
@mixin loader_text_fade(
    $color: $loader-color,
    $size: 1.5rem,
    $duration: 1.5s
) {
    display: inline-flex;
    gap: 0.05em;
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);

    span {
        animation: text-letter-fade $duration ease-in-out infinite;

        @for $i from 1 through 10 {
            &:nth-child(#{$i}) {
                animation-delay: calc(($i - 1) * 0.1s);
            }
        }
    }
}

///
/// Text pulse loader.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [2rem] - Font size.
/// @param {Time} $duration [1s] - Animation duration.
///
@mixin loader_text_pulse(
    $text: 'Loading',
    $color: $loader-color,
    $size: 2rem,
    $duration: $loader-speed
) {
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);
    animation: text-pulse $duration ease-in-out infinite;
}

///
/// Text spotlight/shimmer loader.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color [rgba(255,255,255,0.3)] - Base text color.
/// @param {Color} $highlight [#FFF] - Spotlight highlight color.
/// @param {Length} $size [2rem] - Font size.
/// @param {Time} $duration [2s] - Animation duration.
///
@mixin loader_text_spotlight(
    $text: 'Loading',
    $color: rgba(255, 255, 255, 0.3),
    $highlight: $loader-color,
    $size: 2rem,
    $duration: 2s
) {
    font-size: $size;
    font-weight: 700;
    color: var(--loader-bg, $color);
    background: linear-gradient(
        90deg,
        var(--loader-bg, $color) 0%,
        var(--loader-color, $highlight) 50%,
        var(--loader-bg, $color) 100%
    );
    background-size: 200% 100%;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: text-spotlight $duration linear infinite;
}

///
/// Typing cursor loader.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color [#FFF] - Text color.
/// @param {Color} $cursor-color [#FFF] - Cursor color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [0.8s] - Cursor blink duration.
///
@mixin loader_text_typing(
    $text: 'Loading',
    $color: $loader-color,
    $cursor-color: $loader-color,
    $size: 1.5rem,
    $duration: 0.8s
) {
    font-size: $size;
    font-weight: 500;
    color: var(--loader-color, $color);
    font-family: monospace;

    &::after {
        content: '|';
        color: var(--loader-cursor, $cursor-color);
        animation: text-cursor $duration ease-in-out infinite;
    }
}

///
/// Wave text loader.
///
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [1.2s] - Animation duration.
///
@mixin loader_text_wave(
    $color: $loader-color,
    $size: 1.5rem,
    $duration: 1.2s
) {
    display: inline-flex;
    gap: 0.05em;
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);

    span {
        display: inline-block;
        animation: text-wave $duration ease-in-out infinite;

        @for $i from 1 through 10 {
            &:nth-child(#{$i}) {
                animation-delay: calc(($i - 1) * 0.08s);
            }
        }
    }
}

///
/// Shake text loader.
///
/// @param {String} $text ['Error'] - Text content.
/// @param {Color} $color [#FF3D00] - Text color.
/// @param {Length} $size [1.5rem] - Font size.
/// @param {Time} $duration [0.5s] - Animation duration.
///
@mixin loader_text_shake(
    $text: 'Error',
    $color: $loader-accent,
    $size: 1.5rem,
    $duration: 0.5s
) {
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);
    animation: text-shake $duration ease-in-out infinite;
}

///
/// Gradient flow text loader.
///
/// @param {String} $text ['Loading'] - Text content.
/// @param {Color} $color1 [#FF3D00] - First gradient color.
/// @param {Color} $color2 [#FFF] - Second gradient color.
/// @param {Color} $color3 [#FF3D00] - Third gradient color.
/// @param {Length} $size [2rem] - Font size.
/// @param {Time} $duration [3s] - Animation duration.
///
@mixin loader_text_gradient(
    $text: 'Loading',
    $color1: $loader-accent,
    $color2: $loader-color,
    $color3: $loader-accent,
    $size: 2rem,
    $duration: 3s
) {
    font-size: $size;
    font-weight: 700;
    background: linear-gradient(
        90deg,
        var(--loader-color1, $color1),
        var(--loader-color2, $color2),
        var(--loader-color3, $color3)
    );
    background-size: 200% auto;
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: text-spotlight $duration linear infinite;
}

///
/// Rotating character loader.
///
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [2rem] - Font size.
/// @param {Time} $duration [1s] - Animation duration.
///
@mixin loader_text_spinner(
    $color: $loader-color,
    $size: 2rem,
    $duration: $loader-speed
) {
    font-size: $size;
    color: var(--loader-color, $color);
    display: inline-block;
    animation: spin $duration linear infinite;

    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
}

///
/// Percentage counter loader (requires JS).
///
/// @param {Color} $color [#FFF] - Text color.
/// @param {Length} $size [3rem] - Font size.
///
@mixin loader_text_percentage(
    $color: $loader-color,
    $size: 3rem
) {
    font-size: $size;
    font-weight: 700;
    color: var(--loader-color, $color);
    font-variant-numeric: tabular-nums;
    font-family: monospace;

    &::after {
        content: '%';
    }
}
