@use "sass:map";
@use "sass:string";

@use "../../utilities";
@use "../../variables/units";
@use "../../variables/colors";
@use "../../variables/typography";

@use "button.variables" as button-variables;

// ====================
// Private mixins
// ====================

@mixin _shared-variant($defaults-map, $variant, $state-map: (), $state: "") {
  $map: map.merge($defaults-map, $state-map);

  background-color: var(--_dso-button-#{$variant}#{$state}-background-color, #{map.get($map, "background-color")});
  border-color: var(--_dso-button-#{$variant}#{$state}-border-color, #{map.get($map, "border-color")});
  color: var(--_dso-button-#{$variant}#{$state}-color, #{map.get($map, "color")});
  float: var(--_dt-button-float-#{$variant}, none);
}

@mixin _shared(
  $base-styling,
  $modifiers,
  $defaults-map,
  $hover-map,
  $active-map,
  $disabled-map,
  $icon-only,
  $variant,
  $min-inline-size: button-variables.$min-inline-size
) {
  @if ($base-styling) {
    @include base($modifiers);
  }

  @include _shared-variant($defaults-map, $variant);

  border-width: button-variables.$border-width;
  border-style: solid;
  border-radius: button-variables.$border-radius;
  line-height: typography.$line-height-base;
  min-inline-size: $min-inline-size;
  inline-size: var(--_dt-button-inline-size, auto);
  padding-block: button-variables.$block-padding;
  padding-inline: button-variables.$inline-padding;

  &:hover {
    @include _shared-variant($defaults-map, $variant, $hover-map, "-hover");
  }

  &:active {
    @include _shared-variant($defaults-map, $variant, $active-map, "-active");
  }

  &[disabled] {
    &,
    &:hover {
      @include _shared-variant($defaults-map, $variant, $disabled-map, "-disabled");
    }
  }

  &.dso-small {
    @include small();
  }

  &.dso-extra-small {
    @include small();

    padding-block: 9px;
  }

  @if ($icon-only) {
    > span {
      @include utilities.sr-only();
    }
  } @else if $variant != tertiary {
    dso-icon:has(+ span:not(.sr-only)) {
      margin-inline-start: units.$u1 * -1;
    }

    span:not(.sr-only) + dso-icon {
      margin-inline-start: units.$u1;
      margin-inline-end: units.$u1 * -1;
    }

    dso-icon + span:not(.sr-only) {
      margin-inline-start: units.$u1;
    }
  }
}

@mixin _spinner-icon($color, $valign, $position) {
  background-image: url("data:image/svg+xml,%3Csvg class='spinner' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E .spinner %7B animation: rotator 8s linear infinite; transform-origin: center; %7D @keyframes rotator %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D .path %7B stroke-dasharray: 42.4; stroke-dashoffset: 0; transform-origin: center; stroke: %23#{string.slice(#{$color}, 2)}; animation: dash 2s ease-in-out infinite; %7D @keyframes dash %7B 0%25 %7B stroke-dashoffset: 42.4; %7D 50%25 %7B stroke-dashoffset: 10.4; transform:rotate(90deg); %7D 100%25 %7B stroke-dashoffset: 42.4; transform:rotate(360deg); %7D %3C/style%3E%3Ccircle class='path' fill='none' stroke-width='1.6' stroke-linecap='butt' cx='12' cy='12' r='7.2'%3E%3C/circle%3E%3C/svg%3E");
  background-repeat: no-repeat;
  content: "";
  display: inline-block;
  block-size: units.$u3;
  vertical-align: $valign;
  inline-size: units.$u3;

  @if $position == inline-start {
    margin-inline-end: units.$u1;
  } @else if $position == inline-end {
    margin-inline-start: units.$u1;
  }
}

// ====================
// Public mixins
// ====================

@mixin element() {
  -webkit-appearance: button; // Correct inability to style clickable `input` types in iOS.
  color: inherit;
  cursor: pointer; // Improve usability and consistency of cursor style between image-type `input` and others.
  font: inherit;
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  margin: 0;
  overflow: visible; // Address `overflow` set to `hidden` in IE 8/9/10/11.
  text-transform: none; // Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.

  &[disabled] {
    cursor: default; // Re-set default cursor for disabled elements.
  }

  &::-moz-focus-inner {
    border: 0;
    padding: 0;
  }
}

@mixin icon-only() {
  dso-icon {
    margin-inline-start: 0;
    margin-inline-end: 0;
  }

  > span {
    @include utilities.sr-only();
  }
}

@mixin small() {
  line-height: typography.$root-font-size-base;

  dso-icon,
  &.extern::after,
  &.download::after,
  &.dso-spinner::before {
    margin-block-end: units.$u1 * -0.5;
    margin-block-start: units.$u1 * -0.5;
  }

  &.dso-spinner-left {
    &::before {
      block-size: units.$u2;
      inline-size: units.$u2;
    }
  }

  &.dso-spinner-right {
    &::after {
      block-size: units.$u2;
      inline-size: units.$u2;
    }
  }
}

@mixin base($modifiers: true) {
  display: inline-block;
  font-size: 1em;
  font-weight: 500;
  margin-block-end: 0;
  text-decoration: none;
  touch-action: manipulation;
  text-align: var(--_dt-button-text-align, start);
  user-select: none;
  vertical-align: middle;
  background-clip: padding-box;

  &:focus,
  &:focus-visible {
    outline-offset: 2px; // Normalize between a and button
  }

  &:active {
    outline: 0;
  }

  @if ($modifiers) {
    &.extern,
    &.download {
      &::after {
        content: "";
        display: inline-block;
      }
    }
  }
}

@mixin primary($base-styling: true, $modifiers: true) {
  $defaults-map: (
    "background-color": button-variables.$primary-background-color,
    "border-color": button-variables.$primary-background-color,
    "color": button-variables.$primary-color,
  );

  $hover-map: (
    "background-color": button-variables.$primary-hover-background-color,
    "border-color": button-variables.$primary-hover-background-color,
  );

  $active-map: (
    "background-color": button-variables.$primary-active-background-color,
    "border-color": button-variables.$primary-active-background-color,
  );

  $disabled-map: (
    "background-color": button-variables.$primary-disabled-background-color,
    "border-color": button-variables.$primary-disabled-background-color,
  );

  @include _shared($base-styling, $modifiers, $defaults-map, $hover-map, $active-map, $disabled-map, false, "primary");

  &.dso-spinner-left,
  &.dso-spinner-right {
    &[disabled] {
      background-color: button-variables.$primary-background-color;
      border-color: button-variables.$primary-background-color;
      color: button-variables.$primary-color;
    }
  }

  &.dso-spinner-left {
    &::before {
      @include _spinner-icon($color: colors.$wit, $valign: top, $position: inline-start);
    }
  }

  &.dso-spinner-right {
    &::after {
      @include _spinner-icon($color: colors.$wit, $valign: top, $position: inline-end);
    }
  }
}

@mixin anchor-primary() {
  &,
  &:hover,
  &:visited,
  &:focus-visible {
    color: colors.$wit;
    text-decoration: none;
  }
}

@mixin secondary($base-styling: true, $modifiers: true, $icon-only: false) {
  $defaults-map: (
    "background-color": button-variables.$secondary-background-color,
    "border-color": button-variables.$secondary-border-color,
    "color": button-variables.$secondary-color,
  );

  $hover-map: (
    "background-color": button-variables.$secondary-hover-background-color,
    "border-color": button-variables.$secondary-hover-color,
    "color": button-variables.$secondary-hover-color,
  );

  $active-map: (
    "background-color": button-variables.$secondary-active-background-color,
    "border-color": button-variables.$secondary-active-background-color,
    "color": colors.$wit,
  );

  $disabled-map: (
    "background-color": colors.$wit,
    "border-color": button-variables.$secondary-disabled-color,
    "color": button-variables.$secondary-disabled-color,
  );

  @include _shared(
    $base-styling,
    $modifiers,
    $defaults-map,
    $hover-map,
    $active-map,
    $disabled-map,
    $icon-only,
    "secondary"
  );

  &.dso-spinner-left,
  &.dso-spinner-right {
    &[disabled] {
      background-color: button-variables.$secondary-background-color;
      border-color: button-variables.$secondary-border-color;
      color: button-variables.$secondary-color;
    }
  }

  &.dso-spinner-left {
    &::before {
      @include _spinner-icon($color: colors.$grasgroen, $valign: top, $position: inline-start);
    }

    &:not([disabled]) {
      &:hover {
        &::before {
          @include _spinner-icon($color: colors.$wit, $valign: top, $position: inline-start);
        }
      }

      &.dso-small:hover {
        &::before {
          block-size: units.$u2;
          inline-size: units.$u2;
        }
      }
    }
  }

  &.dso-spinner-right {
    &::after {
      @include _spinner-icon($color: colors.$grasgroen, $valign: top, $position: inline-end);
    }

    &:not([disabled]) {
      &:hover {
        &::after {
          @include _spinner-icon($color: colors.$wit, $valign: top, $position: inline-end);
        }
      }

      &.dso-small:hover {
        &::after {
          block-size: units.$u2;
          inline-size: units.$u2;
        }
      }
    }
  }
}

@mixin anchor-secondary() {
  text-decoration: none;

  &,
  &:visited {
    color: button-variables.$secondary-color;
  }

  &:hover,
  &:focus-visible {
    color: button-variables.$secondary-hover-color;
    text-decoration: none;
  }
}

@mixin tertiary($base-styling: true, $icon-only: false, $modifiers: true) {
  @if ($base-styling) {
    @include base($modifiers);
  }

  $defaults-map: (
    "color": button-variables.$tertiary-color,
  );

  $hover-map: (
    "color": button-variables.$tertiary-hover-color,
  );

  $active-map: (
    "color": button-variables.$tertiary-active-color,
  );

  $disabled-map: (
    "color": colors.$grasgroen-40,
  );

  @include _shared(
    $base-styling,
    $modifiers,
    $defaults-map,
    $hover-map,
    $active-map,
    $disabled-map,
    $icon-only,
    "tertiary",
    auto
  );

  border: 0;
  line-height: 1;
  padding-inline: 0;
  padding-block: var(--_dt-button-padding-block-tertiary, 0);
  background-color: transparent;

  &[disabled] {
    &.dso-spinner-left,
    &.dso-spinner-right {
      color: colors.$grasgroen;
    }
  }

  &:not([disabled]) {
    &:hover {
      text-decoration: underline;
      text-underline-position: under;
    }
  }

  &.dso-align {
    line-height: calc(1.5em - 1px);
    padding-block: button-variables.$tertiary-padding-inline;
    padding-inline: 0;
    position: relative;
  }

  &.dso-truncate {
    max-inline-size: 100%;
    overflow: hidden;
    text-overflow: ellipsis; // stylelint-disable-line declaration-property-value-disallowed-list -- full text can be viewed via tooltip.
    white-space: nowrap; // stylelint-disable-line declaration-property-value-disallowed-list -- full text can be viewed via tooltip.
  }

  &.dso-spinner-left {
    &::before {
      @include _spinner-icon($color: colors.$grasgroen, $valign: middle, $position: inline-start);
    }
  }

  &.dso-spinner-right {
    &::after {
      @include _spinner-icon($color: colors.$grasgroen, $valign: middle, $position: inline-end);
    }
  }

  @if ($icon-only) {
    > span {
      @include utilities.sr-only();
    }
  } @else {
    dso-icon + span:not(.sr-only),
    span:not(.sr-only) + dso-icon {
      margin-inline-start: units.$u1;
    }

    dso-icon[icon="chevron-left"] + span:not(.sr-only),
    dso-icon[icon="chevron-right"] + span:not(.sr-only),
    span:not(.sr-only) + dso-icon[icon="chevron-left"],
    span:not(.sr-only) + dso-icon[icon="chevron-right"] {
      margin-inline-start: 0;
    }

    dso-icon,
    span {
      vertical-align: middle;
    }
  }
}

@mixin anchor-tertiary() {
  text-decoration: none;

  &,
  &:visited {
    color: button-variables.$tertiary-color;
  }
}

@mixin map-box-shadow() {
  box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.5);
}

@mixin map() {
  @include secondary($modifiers: false);

  @include map-box-shadow();

  border: 0;
  font-weight: 600;
  margin-inline-end: units.$u2;
  padding-block: units.$u1;
  padding-inline: units.$u2;
  white-space: nowrap; // stylelint-disable-line declaration-property-value-disallowed-list -- No word wrapping in buttons on maps

  &:focus,
  &:focus-visible {
    outline-offset: -1px;
  }

  &:has(span.sr-only):has(dso-icon) {
    padding: units.$u1;
    min-inline-size: auto;
    block-size: button-variables.$map-size;
    inline-size: button-variables.$map-size;
  }
}
