// RIVER Design-System: System - Functions / Design //

// Design functions used for working with and setting up design maps and values.
// You may choose to load customized versions of these functions as desired.


// COLOR functions

// Build a color range around the given color
// Optionally provide an overrides map to merge into the range
// Optionally choose the amount to shift each color
@function design-color-build-scale($color: null, $overrides: null, $shift: null) {
    // Check for a color
    @if(not $color) {
        @return ();
    }
    // Validate the shift
    $shift: if($shift, $shift, design-setting('colors.shift'));
    // Build the range
    $range: (
        // Range
        900:            design-color-shift($color, 4, $shift),
        800:            design-color-shift($color, 3, $shift),
        700:            design-color-shift($color, 2, $shift),
        600:            design-color-shift($color, 1, $shift),
        500:            design-color-shift($color, 0, $shift),
        400:            design-color-shift($color, -1, $shift),
        300:            design-color-shift($color, -2, $shift),
        200:            design-color-shift($color, -3, $shift),
        100:            design-color-shift($color, -4, $shift),
        50:             design-color-shift($color, -5, $shift),
        // References
        'normal':       500,
    );
    // Merge in overrides
    @if($overrides) {
        $range: map-merge(
            $range,
            $overrides
        );
    }
    // Return
    @return $range;
}

// Shift a color used in the design system
// Used to setup default color ranges and maps (where one has not been provided)
@function design-color-shift($color, $step: 0, $shift: null) {
    $shift: if($shift, $shift, design-setting('colors.shift'));
    @if($step < 0) {
        @return design-color-soften($color, $step * -1, $shift);
    }
    @if($step > 0) {
        @return design-color-intensify($color, $step, $shift);
    }
    @return $color;
}

// Intensify (eg, darken) a color used in the design system
@function design-color-intensify($color, $step: 1, $amount: null) {
    $amountApply: if($step * $amount > 100, 100, $step * $amount);
    @return darken($color, $amountApply);
}

// Soften (eg, lighten) a color used in the design system
@function design-color-soften($color, $step: 1, $amount: null) {
    $amountApply: if($step * $amount > 100, 100, $step * $amount);
    @return lighten($color, $amountApply);
}


// SCALE functions

// Build a power scale, where $n = $base^($multiplier, ($n - 1))
// This is a multiplication based scale that grows exponentially (at an increasing rate)
// This is commonly used for Type Scales
// eg, design-power-scale-build(1em, 1.05, 10, true)
@function design-power-scale-build($base: 1, $multiplier: 1, $count: 1, $includeZero: true) {
    $scale-map: if($includeZero, (0: ($base * 0)), ());
    @for $n from 1 through $count {
        $scale-map: map-merge($scale-map, (
            $n: $base * power-of($multiplier, ($n - 1)),
        ));
    }
    @return $scale-map;
}

// Retrieve the nth value of a power based scale
// eg, design-power-scale-value(5, 1em, 1.05)
@function design-power-scale-value($n: 1, $base: 1, $multiplier: 1) {
    $value: $base * power-of($multiplier, ($n - 1));

    // @error('S', $base, $multiplier, $n, power-of($multiplier, ($n - 1)), $value);

    @return $value;
}

// Build an incremental scale, where $n = $base * ($increments * $n)
// This is an evenly increasing scale that grows at a constant rate
// This is commonly used for size scales, and other scales that should be easy to predict
// eg, design-incremental-scale-build(1rem, 0.5, 10, true)
@function design-incremental-scale-build($base: 1, $increments: 1, $count: 1, $includeZero: true) {
    $scale-map: if($includeZero, (0: ($base * 0)), ());
    @for $n from 1 through $count {
        $scale-map: map-merge($scale-map, (
            $n: $base * ($increments * $n),
        ));
    }
    @return $scale-map;
}

// Retrieve the nth value of an incremental scale
// eg, design-incremental-scale-value(5, 1rem, 0.5)
@function design-incremental-scale-value($n: 1, $base: 1, $increments: 1) {
    $value: $base * ($increments * $n);
    @return $value;
}


// TYPE functions

// Get an adjusted type scale key (constrained to valid type scale values)
@function design-type-scale-shift($key, $step: 0) {
    // Define
    $type-scale-max: design-setting('type.scale.count');
    $key: $key + $step;

    // Constrain
    $key: if($key < 1, 1, $key);
    $key: if($key > $type-scale-max, $type-scale-max, $key);

    // Return valid type scale value
    @return $key;
}

// Build a type scale range around the given base value and multiplier
// Type scales are built using a power / multiplication scale by default
// NOTE, 0 is included by default
// NOTE, the first value in the range is the base value itself
@function design-type-scale-range($base: null, $multiplier: null, $count: null, $includeZero: true) {
    // Design System defaults
    $base: if($base == null, design-setting('type.scale.base'), $base);
    $multiplier: if($multiplier == null, design-setting('type.scale.multiplier'), $multiplier);
    $count: if($count == null, design-setting('type.scale.count'), $count);

    // Build Power Scale
    @return design-power-scale-build($base, $multiplier, $count, $includeZero);
}

// Get a type scale value based on the index and multiplier
@function design-type-scale-value($n: 1, $base: null, $multiplier: null) {
    // Design System defaults
    $base: if($base == null, design-setting('type.scale.base'), $base);
    $multiplier: if($multiplier == null, design-setting('type.scale.multiplier'), $multiplier);

    // Power Scale Value
    @return design-power-scale-value($n, $base, $multiplier);
}


// SIZE functions

// Get an adjusted type scale key (constrained to valid type scale values)
@function design-size-scale-shift($key, $step: 0) {
    // Define
    $size-scale-max: design-setting('sizes.scale.count');
    $key: $key + $step;

    // Constrain
    $key: if($key < 1, 1, $key);
    $key: if($key > $size-scale-max, $size-scale-max, $key);

    // Return valid size scale value
    @return $key;
}

// Build a size scale range around the given base value and increments
// Size scales are built using an incremental scale by default
// NOTE, 0 is included by default
// NOTE, the first value in the range is the base value itself
@function design-size-scale-range($base: null, $increments: null, $count: null, $includeZero: true) {
    // Design System defaults
    $base: if($base == null, design-setting('sizes.scale.base'), $base);
    $increments: if($increments == null, design-setting('sizes.scale.increments'), $increments);
    $count: if($count == null, design-setting('sizes.scale.count'), $count);

    // Build Incremental Scale
    @return design-incremental-scale-build($base, $increments, $count, $includeZero);
}

// Get a size scale value based on the index and increments
@function design-size-scale-value($n: 1, $base: null, $increments: null) {
    // Design System defaults
    $base: if($base == null, design-setting('sizes.scale.base'), $base);
    $increments: if($increments == null, design-setting('sizes.scale.increments'), $increments);

    // Incremental Scale Value
    @return design-incremental-scale-value($n, $base, $increments);
}
