@use 'sass:map';
@use '../utils/constants.scss';
@use '../utils/mixins.scss' as mixins;
@use '../utils/tokens.scss' as tokens;
@use '../utils/animation.scss' as animation;
@use '../utils/cursors.scss' as cursors;

@import '@viasat/beam-tokens/components/Input';

$switchClassBase: '#{constants.$prefix}switch';
$inputChoiceCursor: '--#{constants.$prefix}input-choice-cursor';
$inputChoiceLabelCursor: '--#{constants.$prefix}input-choice-label-cursor';
$inputChoiceLabelPointerEvents: '--#{constants.$prefix}input-choice-label-pointer-events';
$knobOffset: 0.1875rem;
$svgOffset: 0.3125rem;

$switchStates: (
  read-only: (
    backgroundColor: tokens.$bm-comp-input-color-bg-disabled,
    knobColor: tokens.$bm-comp-input-color-icon,
    svgColor: tokens.$bm-comp-input-color-icon,
    borderColor: tokens.$bm-comp-input-color-border-disabled,
    labelColor: tokens.$bm-comp-input-color-text,
  ),
  disabled: (
    backgroundColor: tokens.$bm-comp-input-color-bg-disabled,
    knobColor: tokens.$bm-comp-input-color-icon-disabled,
    svgColor: tokens.$bm-comp-input-color-icon-disabled,
    borderColor: tokens.$bm-comp-input-color-border-disabled,
    labelColor: tokens.$bm-comp-input-color-text-disabled,
  ),
);

.#{$switchClassBase} {
  @include cursors.applyChoiceCursors();

  &__label {
    display: flex;
    position: relative;
    width: fit-content;
    align-items: start;
    gap: tokens.$bm-comp-input-space-choice-gap-inside;
    min-width: tokens.$bm-comp-input-size-choice-switch-width;
    min-height: tokens.$bm-comp-input-size-choice-switch-height;
    font: tokens.$bm-comp-input-typo-md;
    color: tokens.$bm-comp-input-color-text;
    cursor: var(#{$inputChoiceLabelCursor}, pointer);
    pointer-events: var(#{$inputChoiceLabelPointerEvents}, auto);
  }

  input {
    // hide default checkbox
    appearance: none;
    --webkit-appearance: none;
    --moz-appearance: none;

    position: relative;
    display: inline-block;
    flex-shrink: 0;
    width: tokens.$bm-comp-input-size-choice-switch-width;
    height: tokens.$bm-comp-input-size-choice-switch-height;
    margin: tokens.$bm-sem-space-0;
    cursor: var(#{$inputChoiceCursor}, pointer);

    & + .#{$switchClassBase}__switchBackground {
      position: absolute;
      box-sizing: border-box;
      width: tokens.$bm-comp-input-size-choice-switch-width;
      height: tokens.$bm-comp-input-size-choice-switch-height;
      border: tokens.$bm-comp-input-border-width-choice solid
        tokens.$bm-comp-input-color-border;
      border-radius: tokens.$bm-comp-input-radius-choice-switch;
      background-color: tokens.$bm-comp-input-color-bg;
      transition: background-color animation.duration('medium') ease-in-out,
        box-shadow animation.duration('medium') ease-in;

      &:before,
      &:after {
        content: '';
        position: absolute;
        height: tokens.$bm-sem-size-icon-xs;
        width: tokens.$bm-sem-size-icon-xs;
        top: 50%;
        transform: translateY(-50%);
      }

      &:before {
        display: none;
        mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 16.1698L4.83 11.9998L3.41 13.4098L9 18.9998L21 6.99984L19.59 5.58984L9 16.1698Z' fill='currentColor'/%3E%3C/svg%3E");
        left: $svgOffset;
        background-color: tokens.$bm-comp-input-color-icon;
      }

      &:after {
        display: block;
        mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z' fill='currentColor'/%3E%3C/svg%3E");
        right: $svgOffset;
        background-color: tokens.$bm-comp-input-color-icon;
      }
    }

    // switch knob
    &:after {
      // TODO: make sure this doesn't brake layouts
      z-index: 1;
      position: absolute;
      box-sizing: border-box;
      content: '';
      width: tokens.$bm-comp-input-size-choice-switch-knob;
      height: tokens.$bm-comp-input-size-choice-switch-knob;
      top: 50%;
      transform: translateX(0) translateY(-50%);
      left: $knobOffset;
      background-color: tokens.$bm-comp-input-color-icon;
      border-radius: tokens.$bm-sem-radius-round;
      transition: left animation.duration('medium') ease-in-out;
    }

    &:checked {
      & + .#{$switchClassBase}__switchBackground {
        background-color: tokens.$bm-comp-input-color-choice-switch-selected-bg;
        border-color: tokens.$bm-comp-input-color-choice-switch-selected-border;

        &:before {
          display: block;
          background-color: tokens.$bm-comp-input-color-choice-switch-selected-icon;
        }

        &:after {
          display: none;
          background-color: tokens.$bm-comp-input-color-choice-switch-selected-bg;
        }
      }

      &:after {
        background-color: tokens.$bm-comp-input-color-choice-switch-selected-icon;
        left: calc(
          tokens.$bm-comp-input-size-choice-switch-width -
            ($knobOffset + tokens.$bm-comp-input-size-choice-switch-knob)
        );
      }
    }

    &:focus-visible {
      outline: none;

      & + .#{$switchClassBase}__switchBackground {
        @include mixins.simulated-inset-outline(
          tokens.$bm-sem-border-width-focus,
          solid,
          tokens.$bm-sem-color-border-focus,
          tokens.$bm-sem-size-focus-offset
        );
      }
    }
  }

  @each $state, $values in $switchStates {
    &--#{$state} &__label {
      span {
        color: map.get($values, labelColor);
      }
    }

    &--#{$state} input:#{$state} {
      & + .#{$switchClassBase}__switchBackground {
        background-color: map.get($values, backgroundColor);
        border-color: map.get($values, borderColor);

        &:after,
        &:before {
          background-color: map.get($values, svgColor);
        }
      }

      &:after {
        background-color: map.get($values, knobColor);
      }
    }
  }

  // Text Position
  &--before {
    .#{$switchClassBase}__label {
      flex-direction: row-reverse;
    }
  }

  &--after {
    .#{$switchClassBase}__label {
      flex-direction: row;
    }
  }
}
