@use "sass:list";
@use "sass:map";
@use "sass:meta";

@use "../utils" as *;

// ""
// variant-classname("default", "default", "", false),
// ".variant"
// variant-classname("variant", "default", "", false),
// ".prefix"
// variant-classname("default", "default", "prefix", true),
// ".prefix-variant"
// variant-classname("variant", "default", "prefix", true),
// ".prefix"
// variant-classname("default", "default", "prefix", false),
// ".prefix.variant"
// variant-classname("variant", "default", "prefix", false),
@function variant-classname(
  $variant,
  $default: "default",
  $prefix: "",
  $prefix-directly: false
) {
  $variant-ext: null;
  $prefix-ext: null;

  @if is-empty($prefix) and $prefix-directly {
    @error "Invalid variations: empty prefix cant declare in directly style";
  }

  @if $prefix-directly {
    $variant-ext: if-or-empty($variant != $default, $variant);

    $prefix-ext: prefix-if(
      if(is-empty($variant-ext), $prefix, $prefix + "-"),
      "."
    );
  } @else {
    $variant-ext: if-or-empty($variant != $default, ".#{$variant}");
    $prefix-ext: prefix-if($prefix, ".");
  }

  @return "#{$prefix-ext}#{$variant-ext}";
}

// Mixin declare variants declarations by class flag.
// Output declaration like
//
// .mie.<component>.<variant | empty> - for declaration variables
//
// .mie.button.large {
//   --mie-<component>-<property> -- = <property_value>;
//   /*__________________________________________________________________________*/
//   --mie-button-height: 3.4rem;
// }

@mixin variants-assign-variables($class, $vars) {
  $vars: map-flatten($vars);
  $name: kebab-case($class);

  @each $item in $vars {
    $value: list.nth($item, 2);
    $keys: list.nth($item, 1);
    $key: join($keys, "-");

    --mie-#{$name}-#{$key}: #{$value};
  }
}

// This variant declare all variants variables separate from style
// @in:
//   # like "button", "row.item"
//   $class: string
//   # common variants map of variables
//   $variants: map("variant_name": "vars")
//   # default variant variables without status class
//   $default: string
//   # prefix
//   $prefix: if status class need prefix like "size-medium"
//   # prefix directly
//   $prefix-directly: boolean
// @out: all declarations variants
@mixin apply-variants-to-component(
  $class,
  $variants,
  $default: "default",
  $prefix: "",
  $prefix-directly: false
) {
  @if length($variants) > 0 {
    // Its meta in common variants object
    $meta: map.get($variants, "_meta");

    @each $variant-name, $variant-vars in $variants {
      @if $variant-name != "_meta" and length($variant-vars) > 0 {
        $class-name: variant-classname(
          $variant-name,
          $default,
          $prefix,
          $prefix-directly
        );

        .mie.#{$class}#{$class-name} {
          @include variants-assign-variables($class, $variant-vars);
        }
      }
    }
  }
}
