/// Responsive spacing
///
/// Returns a spacing rule for a given property and direction at a given entry
/// in the spacing scale, for all relevant breakpoints.
///
/// Allows the addition of the !important flag.
/// Allows fine tuning by pixel amounts.
///
/// This low-level mixin sholuld rarely be used directly.
/// Use ds_responsive-margin and ds_responsive-padding instead.
///
/// @param {number} $spacing-unit - entry in the spacing scale to get values from
/// @param {string} $property - property to assign a value to
/// @param {string} $direction - direction to apply the value to (leave empty for all directions)
/// @param {boolean} $important - whether to include the !important flag
/// @param {string} $tuning - value to add to the output for fine tuning
/// @param {number} $collapse-spacing-unit - entry in the spacing scale to remove from output
///
/// @returns {string} CSS rule for spacing, e.g. padding-top: 0.5rem
///
/// @example scss
///   .foo {
///     @include ds_responsive-spacing(2, 'padding', top);
///   }

@use "sass:map";
@use "sass:meta";
@use "../../settings";
@use "../media-query";

@mixin ds_responsive-spacing($spacing-unit, $property, $direction: false, $important: false, $tuning: false, $collapse-spacing-unit: false) {
    // validate params
    $spacing-unit-type: meta.type-of($spacing-unit);
    @if $spacing-unit-type != 'number' {
        @error 'Expected an integer for spacing unit but got a #{$spacing-unit-type}';
    }

    @if not map.has-key(settings.$ds_spacing-scale, $spacing-unit) {
        @error 'Spacing unit "#{$spacing-unit}" not found in the spacing scale.';
    }

    @if not map.has-key(settings.$ds_spacing-properties, $property) {
        @error 'Spacing property "#{$property}" not allowed.';
    }

    @if $direction {
        @if not map.has-key(settings.$ds_spacing-directions, $direction) {
            @error 'Invalid spacing direction specified: "#{$direction}"';
        }
    }

    $collapse-values: false;
    @if $collapse-spacing-unit {
        @if not map.has-key(settings.$ds_spacing-scale, $collapse-spacing-unit) {
            @error 'Spacing unit "#{$collapse-spacing-unit}" not found in the spacing scale.';
        }
        $collapse-values: map.get(settings.$ds_spacing-scale, $collapse-spacing-unit);
    }

    $scale-values: map.get(settings.$ds_spacing-scale, $spacing-unit);

    @each $breakpoint, $value in $scale-values {
        @if ($tuning) {
            $value: calc(#{$value} + #{$tuning});
        }
        @if ($collapse-values) {
            $value: calc(#{$value} - #{map.get(settings.$ds_spacing-scale, $collapse-spacing-unit, $breakpoint)});
        }

        @if $breakpoint == null {
            @if not $direction {
                #{$property}: $value if($important, !important, null);
            } @else {
                #{$property}-#{$direction}: $value if($important, !important, null);
            }
        } @else {
            @include media-query.ds_media-query($breakpoint) {
                @if not $direction {
                    #{$property}: $value if($important, !important, null);
                } @else {
                    #{$property}-#{$direction}: $value if($important, !important, null);
                }
            }
        }
    }
}

/// Responsive margin
///
/// Returns a spacing rule for margin at a given entry in the spacing scale,
/// for all relevant breakpoints.
///
/// Allows the addition of the !important flag.
/// Allows fine tuning by pixel amounts.
///
/// @param {number} $spacing-unit - entry in the spacing scale to get values from
/// @param {string} $direction - direction to apply the value to (leave empty for all directions)
/// @param {boolean} $important - whether to include the !important flag
/// @param {string} $tuning - value to add to the output for fine tuning
///
/// @returns {string} CSS rule for margin, e.g. margin-top: 0.5rem
///
/// @example scss
///   .foo {
///     @include ds_responsive-margin(2, top);
///   }

@mixin ds_responsive-margin($spacing-unit, $direction: false, $important: false, $tuning: false, $collapse-spacing-unit: false) {
    @include ds_responsive-spacing($spacing-unit, 'margin', $direction, $important, $tuning, $collapse-spacing-unit);
}

/// Responsive padding
///
/// Returns a spacing rule for padding at a given entry in the spacing scale,
/// for all relevant breakpoints.
///
/// Allows the addition of the !important flag.
/// Allows fine tuning by pixel amounts.
///
/// @param {number} $spacing-unit - entry in the spacing scale to get values from
/// @param {string} $direction - direction to apply the value to (leave empty for all directions)
/// @param {boolean} $important - whether to include the !important flag
/// @param {string} $tuning - value to add to the output for fine tuning
///
/// @returns {string} CSS rule for padding, e.g. padding-top: 0.5rem
///
/// @example scss
///   .foo {
///     @include ds_responsive-padding(2, top);
///   }

@mixin ds_responsive-padding($spacing-unit, $direction: false, $important: false, $tuning: false, $collapse-spacing-unit: false) {
    @include ds_responsive-spacing($spacing-unit, 'padding', $direction, $important, $tuning, $collapse-spacing-unit);
}
