@use "sass:map";
@use "sass:math";

$colors: () !default;

$cache-bg: null;
$cache-fg: null;
$cache-bg-var: null;
$cache-fg-var: null;
$cache-bg-light: null;
$cache-fg-light: null;
$cache-avg-light: null;
$darkmode: null;
$mix-color: null;

$prefix: map.get($settings, "prefix");
@if $prefix != "" {
  $prefix: "#{$prefix}-";
}

@mixin resetColorCache() {
  $cache-bg: null !global;
  $cache-fg: null !global;
  $cache-bg-var: null !global;
  $cache-fg-var: null !global;
  $cache-bg-light: null !global;
  $cache-fg-light: null !global;
  $cache-avg-light: null !global;
  $darkmode: null !global;
  $mix-color: null !global;
}

@function has-color($key, $colorset: $colors) {
  @if type-of($colorset) == "map" {
    @return map.has-key($colorset, $key);
  } @else {
    @warn "colors is not a map but: #{type-of($colorset)}";
    @return false;
  }
}

@function get-color($key, $colorset: $colors) {
  @if type-of($colorset) == "map" {
    @if map.has-key($colorset, $key) {
      @return map.get($colorset, $key);
    } @else {
      @warn "#{$key} does not exist in colors";
    }
  } @else {
    @warn "colors is not a map but: #{type-of($colorset)}";
    @return false;
  }
  @return black;
}

@function getMixColor($color, $colorset: $colors, $cached: true, $name: false) {
  @if $cached {
    @if $cache-bg == null {
      $cache-bg: get-color("background", $colorset) !global;
    }
    @if $cache-fg == null {
      $cache-fg: get-color("foreground", $colorset) !global;
    }
  } @else {
    $cache-bg: get-color("background", $colorset) !global;
    $cache-fg: get-color("foreground", $colorset) !global;
  }

  @if $cache-bg == $color {
    @if $name {
      @return "foreground";
    } @else {
      @return $cache-fg;
    }
  } @else {
    @if $name {
      @return "background";
    } @else {
      @return $cache-bg;
    }
  }
}

@function generateOpacityShades($shade-colors, $shades: (), $cached: true) {
  $add-colors: ();

  $prefix: map.get($settings, "prefix");
  @if $prefix {
    $prefix: "#{$prefix}-";
  }

  @each $name, $value in $shade-colors {
    @if length($shades) > 0 {
      @each $shade in $shades {
        @if $shade != null {
          $color-name: "#{$name}#{$shade}";
          $color-variable: var(--#{$prefix}#{$name}-rgb);
          $color-value: rgba($color-variable, 0.01 * $shade);
          $add-colors: map.set($add-colors, $color-name, $color-value);
        }
      }
    }
  }
  @return $add-colors;
}
@function generateColorMixShades($shade-colors, $shades: (), $cached: true) {
  $add-colors: ();

  $prefix: map.get($settings, "prefix");
  @if $prefix {
    $prefix: "#{$prefix}-";
  }

  @each $name, $value in $shade-colors {
    @if length($shades) > 0 {
      @each $shade in $shades {
        @if $shade != null {
          $color-name: "#{$name}#{$shade}";

          $name-variable-var: var(--#{$prefix}#{$name});
          $mix-color-var: var(
            --#{$prefix}#{getMixColor($value, $shade-colors, $cached, true)}
          );
          $color-value: "color-mix(in srgb, #{$name-variable-var} #{percentage(math.div($shade,100))}, #{$mix-color-var})";
          $add-colors: map.set($add-colors, $color-name, $color-value);
        }
      }
    }
  }
  @return $add-colors;
}

@function generateShades($shade-colors, $shades: (), $cached: true) {
 $add-colors: ();

  @each $name, $value in $shade-colors {
    @if length($shades) > 0 {
      @each $shade in $shades {
        $color-name: "#{$name}#{$shade}";
        $mix-color: getMixColor($value, $shade-colors, $cached);
        $color-value: get-mix($value, $mix-color, $shade);
        $add-colors: map.set($add-colors, $color-name, $color-value);
      }
    }
  }

  @return $add-colors;
}

@function fix-color($color-string) {
  $color-name: str-replace(str-replace($color-string,'var(--#{$prefix}',''),')','');
  @return get-color($color-name);
}

@function get-mix($c1, $c2, $amount) {
  @if type-of($c1) == "color" and type-of($c2) == "color" {
    @return mix($c1, $c2, $amount);
  } @else {
    @if type-of($c1) != "color" {
      $c1: fix-color($c1);
    }
    @if type-of($c2) != "color" {
      $c2: fix-color($c2);
    }
    @return mix($c1, $c2, $amount);
  }
}

@function get-red($clr) {
  @if type-of($clr) == "color" {
    @return red($clr);
  } @else {
    @return red(fix-color($clr));
  }
}

@function get-blue($clr) {
  @if type-of($clr) == "color" {
    @return blue($clr);
  } @else {
    @return red(fix-color($clr));
  }
}

@function get-green($clr) {
  @if type-of($clr) == "color" {
    @return green($clr);
  } @else {
    @return green(fix-color($clr));
  }
}

@function generateTextColor($text-colors) {
  $add-colors: ();

  @each $name, $value in $text-colors {
    $color-name: "#{$name}Text";
    $color-value: getTextColor($value);
    $add-colors: map.set($add-colors, $color-name, $color-value);
  }
  @return $add-colors;
}

@function text-contrast($color, $dark: black, $light: white) {
  $brightness: round(
    (get-red($color) * 299)+ (get-green($color) * 587) + math.div((get-blue(
              $color
            ) * 114), 1000)
  );
  $whiteness: round(
    (get-red(#ffffff) * 299)+ (get-green(#ffffff) * 587) + math.div((get-blue(
              #ffffff
            ) * 114), 1000)
  );
  @if abs($brightness) < math.div($whiteness, 2) {
    @return $dark;
  } @else {
    @return $light;
  }
}

@function getTextColor($color-value) {
  @if $cache-bg == null {
    $cache-bg: get-color("background") !global;
  }
  @if $cache-fg == null {
    $cache-fg: get-color("foreground") !global;
  }
  @if $cache-bg-var == null {
    $cache-bg-var: #{variable(background)} !global;
  }
  @if $cache-bg-light == null {
    $cache-bg-light: lightness($cache-bg) !global;
  }
  @if $cache-fg-light == null {
    $cache-fg-light: lightness($cache-fg) !global;
  }
  @if $cache-fg-var == null {
    $cache-bg-var: white !global;
    $cache-fg-var: #{variable(foreground)} !global;
  }

  @if $cache-avg-light == null {
    $cache-avg-light: math.div(($cache-bg-light + $cache-fg-light), 2) !global;
  }

  @if $darkmode == null {
    $darkmode: ($cache-bg-light > $cache-fg-light) !global;
  }

  $light: var(--#{$prefix}light);
  $dark: var(--#{$prefix}dark);

  @if $darkmode {
    $dark: var(--#{$prefix}light);
    $light: var(--#{$prefix}dark);
  }

  $color-value: text-contrast($color-value, $dark, $light);

  @return $color-value;
}

@function toRgb($str) {
  $list: str-to-list($str, ",");

  @return rgb(
    parseInt(nth($list, 1)),
    parseInt(nth($list, 2)),
    parseInt(nth($list, 3))
  );
}

@function toMode($mode, $clrs) {
  $mode-colors: ();

  $bg: map.get($clrs, "background");
  $fg: map.get($clrs, "foreground");

  $og-bg: $bg;
  $og-fg: $fg;

  @if type-of($bg) == "string" {
    $bg: toRgb($bg);
  }
  @if type-of($fg) == "string" {
    $fg: toRgb($fg);
  }

  $bg-lightness: lightness($bg);
  $fg-lightness: lightness($fg);

  @if $bg-lightness < $fg-lightness {
    $current: "dark";
  }
  $current: "light";

  @if $mode == $current {
    @return $clrs;
  } @else {
    @return map.merge(
      $clrs,
      (
        background: $og-fg,
        foreground: $og-bg,
      )
    );
  }
}

@function toVars($clrs, $mode, $rgb: true) {
  $varred: ();

  @each $name, $value in $clrs {
    $var-name: $name;
    @if $mode == "dark" {
      @if $name == "background" {
        $var-name: "dark";
      }
      @if $name == "foreground" {
        $var-name: "light";
      }
    } @else {
      @if $name == "background" {
        $var-name: "light";
      }
      @if $name == "foreground" {
        $var-name: "dark";
      }
    }

    $variable: var(--#{$prefix}#{$var-name}-rgb);
    @if $rgb {
      $variable: rgba($variable, 1);
    }

    $varred: map.set($varred, $name, $variable);
  }

  @return $varred;
}

@function addDark($clrs) {
  $bg: map.get($clrs, "background");
  $fg: map.get($clrs, "foreground");



  // @debug "background: #{$bg}";
  // @debug "foreground: #{$fg}";

  @return $clrs;
  // $bg-lightness: lightness($bg);
  // $fg-lightness: lightness($fg);

  // $dark: $fg;
  // @if $bg-lightness < $fg-lightness {
  //   $dark: $bg;
  // }

  // @return map.merge(
  //   $clrs,
  //   (
  //     dark: $dark,
  //   )
  // );
}
@function addLight($clrs) {
  $bg: map.get($clrs, "background");
  $fg: map.get($clrs, "foreground");


  
  $bg-lightness: lightness($bg);
  $fg-lightness: lightness($fg);

  $light: $bg;
  @if $bg-lightness < $fg-lightness {
    $light: $fg;
  }

  @return map.merge(
    $clrs,
    (
      light: $light,
    )
  );
}

@function addRGB($clrs) {
  $rgb: ();

  @each $color-name, $v in $clrs {
    $rgb: map.merge(
      $rgb,
      (
        $color-name: "#{get-red($v)}, #{get-green($v)}, #{get-blue($v)}",
      )
    );
  }
  @return $rgb;
}

@function rgbValues($clr) {
  @return "#{get-red($clr)}, #{get-green($clr)}, #{get-blue($clr)}";
}

@function filterColors($clrs, $mode, $values) {
  $newColors: ();

  @if $mode == "include" {
    @each $name, $value in $clrs {
      @if list-contains($values, $name) {
        $newColors: map.set($newColors, $name, $value);
      }
    }
  } @else if $mode == "exclude" {
    @each $name, $value in $clrs {
      @if not list-contains($values, $name) {
        $newColors: map.set($newColors, $name, $value);
      }
    }
  }

  @return $newColors;
}

@function addAffix($clrs, $affix) {
  $newColors: ();

  @if $affix {
    $affix: "-#{$affix}";
  }

  @each $name, $value in $clrs {
    $newColors: map.set($newColors, "#{$name}#{$affix}", $value);
  }
  @return $newColors;
}
