/**
 Schemes wrapper
 */

$dm: '.#{$prefix}-dark-mode';

$scheme-wrapper-selectors:() !global;
$scheme-elements:() !global;
$scheme-elements-transitions:() !global;

/** new version **/

/** private */

@function _str-replace($stack, $needle, $content) {
  $is:quote($stack);
  $in:quote($needle);
  $ic:quote($content);

  $i:str-index($is, $in);

  @while $i != null {
    $is:unquote(str_slice($is, 1, $i - 1) + $ic + str_slice($is, $i + str-length($in), str_length($is)));
    $i:str-index($is, $in);
  }

  @return unquote($is);
}

@function _replace_color($value, $hex, $url-encode:true) {
  @if $url-encode == true {
    $hex:unquote('%23' + str_slice(inspect($hex), 2));
  }

  @return _str-replace($value, $COLOR, $hex);
}

/** private */
@function _scheme-set-color($set, $scheme-type) {
  $result:null;
  $i: 0;

  @each $type, $variation in $scheme-wrappers {
    $i: $i + 1;
    @if $scheme-type == $type and length($set) >= $i {
      @return nth($set, $i);
    }
  }

  @return nth($set, 1);
}

/** private **/
@mixin _theme-transition() {
  @at-root #{$theme-transition-selector} & {
    @content;
  }
}

@mixin _get-hover-vars($color) {

  @if opacity($color) != 0 {

    $lightness: lightness($color);

    @if $lightness > 50% {
      $c:$lightness / 100%;

      --hover-shade: 0;
      --hover-opacity: #{0.08 / $c};
    }
    @else {
      $c: (1 - ($lightness / 100%));

      --hover-shade: 255;
      --hover-opacity: #{0.16 / $c};
    }
  }
}

@mixin define-vars {
  #{$dark-theme-selector} {
    @each $name, $set in $scheme-sets {
      --#{$name}: #{_scheme-set-color($set, dark)};
    }
  }

  :root {
    @each $name, $set in $scheme-sets {
      --#{$name}: #{_scheme-set-color($set, light)};
    }
  }

  #{$not-dark-theme-selector} {
    $i: 0;
    @each $type, $variation in $scheme-wrappers {
      $i: ($i + 1);

      [class*="#{$base-scheme}-#{$type}"],
      [class*="--scheme-#{$type}-"] {
        @each $name, $set in $scheme-sets {
          @if length($set) >= $i {
            --#{$name}: #{_scheme-set-color($set, $type)};
          }
        }
      }
    }
  }
}

/** private **/
@mixin _box-shadow-border($var, $width: 0 0 0 0) {
  $tw:nth($width, 1);
  $rw:nth($width, 2);
  $bw:nth($width, 3);
  $lw:nth($width, 4);

  @if $lw == 0 and $tw == 0 {
    @if $rw == 0 and $bw == 0 {
      //no action
    }
    @else {
      box-shadow: inset #{-($rw)} #{-($bw)} 0 0 $var;
    }
  }
  @else {
    @if $rw == 0 and $bw == 0 {
      box-shadow: inset $lw $tw 0 0 $var;
    }
    @else {
      box-shadow: inset $lw $tw 0 0 $var, inset #{-($rw)} #{-($bw)} 0 0 $var;
    }
  }
}

/** private */
@mixin _scheme-wrapper-border($module, $width:1px) {

  $base:'#{$module}-border';
  $w:$width;

  @if length($width) == 1 {
    $w: $width $width $width $width;
  }
  @else if length($width) == 2 {
    $w: nth($width, 1) nth($width, 2) nth($width, 1) nth($width, 2);
  }
  @else if length($width) == 3 {
    $w: nth($width, 1) nth($width, 2) nth($width, 3) nth($width, 2);
  }

  $l:('':0,'#{$base}--left': nth($w, 1));
  $t:('':0,'#{$base}--top': nth($w, 2));
  $r:('':0,'#{$base}--right': nth($w, 3));
  $b:('':0,'#{$base}--bottom': nth($w, 4));

  &#{$base} {
    @include _box-shadow-border(var(--scheme-border), $w);

    @each $ln, $lp in $l {
      @each $tn, $tp in $t {
        @each $rn, $rp in $r {
          @each $bn, $bp in $b {
            @if $lp != 0 or $tp != 0 or $rp != 0 or $bp != 0 {
              &#{$ln}#{$tn}#{$rn}#{$bn} {
                @include _box-shadow-border(var(--scheme-border), $tp $rp $bp $lp);
              }
            }
          }
        }
      }
    }
  }
}

/** private */
@function _get-scheme($type, $name, $index:0) {
  $list: map_get(map_get($scheme-wrappers, $type), $name);

  @if $index == 0 {
    @return $list;
  }

  @return nth($list, $index);
}

/** private **/
@mixin _add-scheme-color-set($selector, $module, $type, $color, $sets, $borders) {
  $set: map_get($scheme-sets, nth($sets, 1));

  @at-root #{$selector}-#{$color} {
    background-color: var(--#{nth($sets, 1)});

    --scheme-border: var(--#{nth($sets, 2)});

    @include _get-hover-vars(_scheme-set-color($set, light));

    @if $borders == true {
      @include _scheme-wrapper-border($module, space(0-5N));
    }
  }

  @at-root #{$dark-theme-selector} #{$selector}-#{$color} {
    @include _get-hover-vars(_scheme-set-color($set, dark));
  }
}

/** private **/
@mixin _add-scheme-wrapper($selector, $module, $type:light, $borders:true) {
  @each $color, $sets in map_get($scheme-wrappers, $type) {
    @include _add-scheme-color-set($selector, $module, $type, $color, $sets, $borders);
  }

  @at-root #{$selector} {
    @include _theme-transition() {
      transition: background-color $theme-transition-duration, box-shadow $theme-transition-duration;
    }
  }
}

/**
 initialize wrappers.
 */
@mixin scheme-wrappers {

  $sets: _get-scheme(light, white);

  @at-root body {
    background-color: var(--#{nth($sets, 1)});

    @include _theme-transition() {
      transition: background-color $theme-transition-duration;
    }
  }

  @each $type, $variation in $scheme-wrappers {
    @include _add-scheme-wrapper(#{$base-scheme-selector}-#{$type}, #{$base-scheme-selector}, $type, false);
  }
}

@mixin component-as-scheme($type:light, $color:grey-100, $modifier:false, $width: none) {

  $selector: &;

  @if $modifier and $type != light {
    $selector: #{&}--scheme-#{$type}-#{$color};
  }

  @at-root #{$selector} {
    $sets: _get-scheme($type, $color);
    background-color: var(--#{nth($sets, 1)});

    --scheme-border: var(--#{nth($sets, 2)});

    @if $width != none {
      @include _box-shadow-border(var(--scheme-border), $width);
    }

    @content;
  }
}

@mixin component-as-scheme-modifiers($type, $width: none) {
  $variation: map_get($scheme-wrappers, $type);

  @each $color, $sets in $variation {
    @include component-as-scheme($type, $color, true);
  }

  @if $width != none {
    @include _box-shadow-border(var(--scheme-border), $width);
  }
}

/**
 Scheme set
 */

/** private */
@mixin _scheme-element-hover($pseudo:before, $position:relative) {

  position: $position;

  &::#{$pseudo} {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(var(--hover-shade), var(--hover-shade), var(--hover-shade), 0);
  }

  &:hover::#{$pseudo} {
    background-color: rgba(var(--hover-shade), var(--hover-shade), var(--hover-shade), var(--hover-opacity));
  }

  &:active::#{$pseudo} {
    background-color: rgba(var(--hover-shade), var(--hover-shade), var(--hover-shade), calc(var(--hover-opacity) * 2));
  }
}

/** private */
@mixin _scheme-element($name, $prop, $transition:true, $hover:false, $value:$COLOR, $url-encode:false, $element:&) {
  $set: map_get($scheme-sets, $name);

  //$element: _sanitize_selector($element);

  $light: _scheme-set-color($set, light);
  $dark: _scheme-set-color($set, dark);

  $h: quote($hover);
  $i: str-index($h, '-');
  $position: relative;

  @if $i != null {
    $hover: unquote(str_slice($h, 1, $i - 1));
    $position: unquote(str_slice($h, $i + 1));
  }

  $pseudo:before;

  @if $hover == after {
    $pseudo:after;
  }

  @if $hover != false {
    @at-root {
      #{$element} {
        @include _scheme-element-hover($pseudo, $position);
      }

      #{$not-dark-theme-selector} {
        #{$element} {
          @include _get-hover-vars($light);
        }

        $i: 0;
        @each $type, $variation in $scheme-wrappers {
          $i: ($i + 1);

          [class*="#{$base-scheme}-#{$type}"],
          [class*="--scheme-#{$type}-"] {
            #{$element} {
              @include _get-hover-vars(_scheme-set-color($set, $type));
            }
          }
        }
      }

      #{$dark-theme-selector} #{$element} {
        @include _get-hover-vars($dark);
      }
    }
  }

  #{$prop}: _replace_color($value, var(--#{$name}), false);
}

@mixin scheme-element-bg-color($set-name, $transition:true, $hover:false) {
  @include _scheme-element($set-name, background-color, $transition, $hover);
}

@mixin scheme-element-text-color($set-name, $transition:true) {
  @include _scheme-element($set-name, color, $transition);
}

@mixin scheme-element-fill-color($set-name, $transition:true) {
  @include _scheme-element($set-name, fill, $transition);
}

@mixin scheme-element-border-color($set-name, $transition:true, $side:null, $value:1px solid $COLOR) {
  $prop:border;
  @if $side != null {
    $prop:border-#{$side};
  }
  @include _scheme-element($set-name, $prop, $transition, false, $value);
}

@mixin scheme-element-outline-color($set-name, $transition:true, $value:1px solid $COLOR) {
  @include _scheme-element($set-name, outline, $transition, false, $value);
}

@mixin scheme-element-box-shadow-color($set-name, $transition:true, $value:inset 0 0 0 1px $COLOR) {
  @include _scheme-element($set-name, box-shadow, $transition, false, $value);
}

@mixin scheme-element-data-uri-svg($set-name, $value, $prop:background-image) {
  $set: map-get($scheme-sets, $set-name);

  --data-uri-svg: #{_replace_color($value, _scheme-set-color($set, light), true)};

  #{$dark-theme-selector} & {
    --data-uri-svg: #{_replace_color($value, _scheme-set-color($set, dark), true)};
  }

  #{$not-dark-theme-selector} {
    $i: 0;
    @each $type, $variation in $scheme-wrappers {
      $i: ($i + 1);
      [class*="#{$base-scheme}-#{$type}"] & {
        @if length($set) >= $i {
          --data-uri-svg: #{_replace_color($value, _scheme-set-color($set, light), true)};
        }
      }
    }
  }

  #{$prop}: var(--data-uri-svg);
}

@mixin scheme-element-focus() {
  &:focus {
    @include scheme-element-outline-color(focus, false, 2px solid $COLOR);
    outline-offset: 2px;
    z-index: var(--focus-z-index);
  }
}
