@use "sass:math";

@import "./form";

$toggle-switch-size-default: 18px;
$toggle-switch-size-large: 28px;

@mixin toggleComputedStyles($size) {
  $border-width: 2px;
  $width: $size * 2 - ($border-width * 2);
  $animation-extra-width: round(math.div($size, 8));
  $toggle-switch-focus-offset: math.div($size, 10);

  .cobalt- {
    &ToggleSwitchField {
      &__ToggleSwitchSlider {
        width: $width;
        height: $size;

        border-radius: $size;
      }

      &__ToggleSwitchSlider:before {
        height: $size - ($border-width * 2);
        width: $size - ($border-width * 2);

        border-radius: $size;

        box-shadow: 0 2px math.div($size, 5) 0 rgba(0, 0, 0, 0.3);
      }

      &__ToggleSwitchSlider:after {
        top: -$toggle-switch-focus-offset;
        left: -$toggle-switch-focus-offset;

        height: calc(100% + #{($toggle-switch-focus-offset) * 2});
        width: calc(100% + #{($toggle-switch-focus-offset) * 2});

        border-radius: $size;
      }

      &__Input {
        &:not([disabled])
          + .cobalt-ToggleSwitchField__ToggleSwitch
          .cobalt-ToggleSwitchField__ToggleSwitchSlider:active:before {
          width: $size + $animation-extra-width;
        }

        &:checked
          + .cobalt-ToggleSwitchField__ToggleSwitch
          .cobalt-ToggleSwitchField__ToggleSwitchSlider:before {
          transform: translateX($width - $size);
        }

        &:not([disabled]):checked:active
          + .cobalt-ToggleSwitchField__ToggleSwitch
          .cobalt-ToggleSwitchField__ToggleSwitchSlider:before {
          transform: translateX(
            $width - $size - $animation-extra-width - ($border-width * 2)
          );
        }

        &:not([disabled]):active
          + .cobalt-ToggleSwitchField__ToggleSwitch
          .cobalt-ToggleSwitchField__ToggleSwitchSlider:before {
          width: $size + $animation-extra-width;
        }
      }
    }
  }
}

.cobalt- {
  &ToggleSwitchField {
    $animation-duration: 200ms;

    @include form-field-container;
    @include toggleComputedStyles($toggle-switch-size-default);

    position: relative;

    @apply c-mb-xs;

    align-items: center;
    flex-direction: row;
    justify-content: flex-end;

    &:not(.cobalt-ToggleSwitchField--standalone) {
      display: block;
    }

    &__LabelWrapper {
      position: relative;

      flex: 1;
      display: flex;
      justify-content: flex-end;
      align-items: center;
      flex-direction: row-reverse;
    }

    &__Label {
      @apply c-text-body-md c-text-base c-p-none c-pr-sm;
      display: inline-block;

      flex: 1;
    }

    &__ToggleSwitch {
      position: relative;

      top: 1px;

      display: flex;
      justify-content: center;
      align-items: center;
    }

    &__ToggleSwitchSlider {
      @include semantic-color(stroke, base, background-color);
      display: inline-block;

      transition: $animation-duration;
    }

    &__ToggleSwitchSlider:before {
      position: absolute;

      left: 2px;
      bottom: 2px;

      content: "";

      // Toggle switch slider will always be white in any cases
      background-color: #fff;

      transition: $animation-duration;
      will-change: transform;
    }

    &__ToggleSwitchSlider:after {
      @apply c-text-accent;
      position: absolute;

      opacity: 0;

      box-shadow: 0 0 0 1px;

      content: "";
    }

    &__Input {
      position: absolute;

      width: 0;
      height: 0;
      margin: 0;
      padding: 0;

      opacity: 0;

      &:checked
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-bg-fill-accent;
      }

      &:not([disabled]) + .cobalt-ToggleSwitchField__ToggleSwitch,
      &:not([disabled]) ~ .cobalt-ToggleSwitchField__Label {
        cursor: pointer;
      }

      &:not([disabled]):focus
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider:after {
        opacity: 1;
      }

      &[disabled]
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-bg-fill-disabled;
      }

      &[disabled]
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider:before {
        box-shadow: none;
      }

      &[disabled]:checked
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-bg-fill-accent;
        opacity: 0.5;
      }

      &[disabled] ~ .cobalt-ToggleSwitchField__Label {
        @apply c-text-subdued;
        opacity: 0.7;
      }

      &:focus
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider:after {
        opacity: 1;
      }
    }

    &--error {
      .cobalt-ToggleSwitchField__Input
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-border-error c-border-2;
      }

      .cobalt-ToggleSwitchField__Input:focus
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-border-error c-border-2;
      }

      .cobalt-ToggleSwitchField__Input:checked
        + .cobalt-ToggleSwitchField__ToggleSwitch
        .cobalt-ToggleSwitchField__ToggleSwitchSlider {
        @apply c-bg-fill-negative;
      }
    }

    .cobalt-Hint {
      @apply c-mt-xs c-mr-none c-mb-none c-ml-[1px];
    }

    &--large {
      @include toggleComputedStyles($toggle-switch-size-large);
    }

    &--standalone {
      width: auto;
    }

    &--position-left {
      width: auto;

      .cobalt-ToggleSwitchField__LabelWrapper {
        flex-direction: row;
      }

      .cobalt-ToggleSwitchField__Label {
        @apply c-p-none c-pl-sm;
      }
    }
  }
}
