$polaris-spacing: (
        'none': 0,
        'extra-tight': 4px,
        'tight': 8px,
        'base-tight': 12px,
        'base': 16px,
        'loose': 20px,
        'extra-loose': 32px,
);
$default-browser-font-size: 16px;
$base-font-size: 10px;

@function spacing($variant: base) {
  $fetched-value: map-get($polaris-spacing, $variant);

  @if type-of($fetched-value) == number {
    @return rem($fetched-value);
  } @else {
    @error 'Spacing variant `#{$variant}` not found. Available variants: #{available-names($polaris-spacing)}';
  }
}

@function rem($value) {
  $unit: unit($value);

  @if $value == 0 {
    @return 0;
  } @else if $unit == 'rem' {
    @return $value;
  } @else if $unit == 'px' {
    @return $value / $base-font-size * 1rem;
  } @else if $unit == 'em' {
    @return $unit / 1em * 1rem;
  } @else {
    @error 'Value must be in px, em, or rem.';
  }
}

@function available-names($map, $level: 1) {
  @if type-of($map) != 'map' {
    @return null;
  }

  $output: '';
  $newline: '\A ';

  @if $level == 1 {
    @each $key, $value in $map {
      $output: $output +
        '#{$newline}- #{$key} #{available-names($value, $level + 1)}';
    }
  } @else {
    $output: '(';
    $i: 1;

    @each $key, $value in $map {
      $sep: if($i < length($map), ', ', '');
      $output: $output + '#{$key}#{$sep}#{available-names($value, $level + 1)}';
      $i: $i + 1;
    }

    $output: $output + ')';
  }

  @return $output;
}

//Functions for Colors and Theme
@function map-deep-set($map, $keys, $value) {
  $maps: ($map,);
  $result: null;

  // If the last key is a map already
  // Warn the user we will be overriding it with $value
  @if type-of(nth($keys, -1)) == "map" {
    @warn "The last key you specified is a map; it will be overrided with `#{$value}`.";
  }

  // If $keys is a single key
  // Just merge and return
  @if length($keys) == 1 {
    @return map-merge($map, ( $keys: $value ));
  }

  // Loop from the first to the second to last key from $keys
  // Store the associated map to this key in the $maps list
  // If the key doesn't exist, throw an error
  @for $i from 1 through length($keys) - 1 {
    $current-key: nth($keys, $i);
    $current-map: nth($maps, -1);
    $current-get: map-get($current-map, $current-key);

    @if $current-get == null {
      @error "Key `#{$key}` doesn't exist at current level in map.";
    }
    $maps: append($maps, $current-get);
  }

  // Loop from the last map to the first one
  // Merge it with the previous one
  @for $i from length($maps) through 1 {
    $current-map: nth($maps, $i);
    $current-key: nth($keys, $i);
    $current-val: if($i == length($maps), $value, $result);
    $result: map-merge($current-map, ($current-key: $current-val));
  }

  // Return result
  @return $result
}
@function map-deep-get($map, $keys...) {
  @each $key in $keys {
    $map: map-get($map, $key);
  }
  @return $map
}

// Adapted from https://gist.github.com/pentzzsolt/4949bbd7691d43d00616dc4f1451cae9#file-non-destructive-map-merge-4-scss
@function map-deep-merge($parent-map, $child-map) {
  $result: $parent-map;
  @each $key, $child in $child-map {
    $parent-has-key: map-has-key($result, $key);
    $parent-value: map-get($result, $key);
    $parent-type: type-of($parent-value);
    $child-type: type-of($child);
    $parent-is-map: $parent-type == map;
    $child-is-map: $child-type == map;

    @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)) {
      $result: map-merge($result, ( $key: $child ))
    }

    @else {
      $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
    }
  }

  @return $result
}

