@use '../core/tokens/m2/mdc/radio' as tokens-mdc-radio;
@use '../core/tokens/token-utils';

$_icon-size: 20px;

@function _enter-transition($name) {
  @return $name 90ms cubic-bezier(0, 0, 0.2, 1);
}

@function _exit-transition($name) {
  @return $name 90ms cubic-bezier(0.4, 0, 0.6, 1);
}

// Structural styles for a radio button. Shared with the selection list.
@mixin radio-structure($is-interactive) {
  $tokens: tokens-mdc-radio.$prefix, tokens-mdc-radio.get-token-slots();

  .mdc-radio {
    display: inline-block;
    position: relative;
    flex: 0 0 auto;
    box-sizing: content-box;
    width: $_icon-size;
    height: $_icon-size;
    cursor: pointer;

    // This is something we inherited from MDC, but it shouldn't be necessary.
    // Removing it will likely lead to screenshot diffs.
    will-change: opacity, transform, border-color, color;

    @include token-utils.use-tokens($tokens...) {
      $size-token: token-utils.get-token-variable(state-layer-size);
      padding: calc((#{$size-token} - #{$_icon-size}) / 2);
    }

    @if ($is-interactive) {
      // MDC's hover indication comes from their ripple which we don't use.
      &:hover .mdc-radio__native-control:not([disabled]):not(:focus) {
        & ~ .mdc-radio__background::before {
          opacity: 0.04;
          transform: scale(1);
        }
      }

      &:hover .mdc-radio__native-control:not([disabled]) ~ .mdc-radio__background {
        .mdc-radio__outer-circle {
          @include token-utils.use-tokens($tokens...) {
            @include token-utils.create-token-slot(border-color, unselected-hover-icon-color);
          }
        }
      }

      &:hover .mdc-radio__native-control:enabled:checked + .mdc-radio__background {
        .mdc-radio__outer-circle,
        .mdc-radio__inner-circle {
          @include token-utils.use-tokens($tokens...) {
            @include token-utils.create-token-slot(border-color, selected-hover-icon-color);
          }
        }
      }

      &:active .mdc-radio__native-control:enabled:not(:checked) + .mdc-radio__background {
        .mdc-radio__outer-circle {
          @include token-utils.use-tokens($tokens...) {
            @include token-utils.create-token-slot(border-color, unselected-pressed-icon-color);
          }
        }
      }

      &:active .mdc-radio__native-control:enabled:checked + .mdc-radio__background {
        .mdc-radio__outer-circle,
        .mdc-radio__inner-circle {
          @include token-utils.use-tokens($tokens...) {
            @include token-utils.create-token-slot(border-color, selected-pressed-icon-color);
          }
        }
      }
    }
  }

  .mdc-radio__background {
    display: inline-block;
    position: relative;
    box-sizing: border-box;
    width: $_icon-size;
    height: $_icon-size;

    &::before {
      position: absolute;
      transform: scale(0, 0);
      border-radius: 50%;
      opacity: 0;
      pointer-events: none;
      content: '';
      transition: _exit-transition(opacity), _exit-transition(transform);

      @include token-utils.use-tokens($tokens...) {
        $size: token-utils.get-token-variable(state-layer-size);
        $offset: calc(-1 * (#{$size} - #{$_icon-size}) / 2);
        width: $size;
        height: $size;
        top: $offset;
        left: $offset;
      }
    }
  }

  .mdc-radio__outer-circle {
    position: absolute;
    top: 0;
    left: 0;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    border-width: 2px;
    border-style: solid;
    border-radius: 50%;
    transition: _exit-transition(border-color);
  }

  .mdc-radio__inner-circle {
    position: absolute;
    top: 0;
    left: 0;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    transform: scale(0, 0);
    border-width: 10px;
    border-style: solid;
    border-radius: 50%;
    transition: _exit-transition(transform), _exit-transition(border-color);
  }

  .mdc-radio__native-control {
    position: absolute;
    margin: 0;
    padding: 0;
    opacity: 0;
    top: 0;
    right: 0;
    left: 0;
    cursor: inherit;
    z-index: 1;

    @include token-utils.use-tokens($tokens...) {
      @include token-utils.create-token-slot(width, state-layer-size);
      @include token-utils.create-token-slot(height, state-layer-size);
    }

    &:checked, &:disabled {
      + .mdc-radio__background {
        transition: _enter-transition(opacity), _enter-transition(transform);

        .mdc-radio__outer-circle {
          transition: _enter-transition(border-color);
        }

        .mdc-radio__inner-circle {
          transition: _enter-transition(transform), _enter-transition(border-color);
        }
      }
    }

    @if ($is-interactive) {
      &:focus + .mdc-radio__background::before {
        transform: scale(1);
        opacity: 0.12;
        transition: _enter-transition(opacity), _enter-transition(transform);
      }
    }

    &:disabled {
      @include token-utils.use-tokens($tokens...) {
        &:not(:checked) + .mdc-radio__background .mdc-radio__outer-circle {
          @include token-utils.create-token-slot(border-color, disabled-unselected-icon-color);
          @include token-utils.create-token-slot(opacity, disabled-unselected-icon-opacity);
        }

        + .mdc-radio__background {
          cursor: default;

          .mdc-radio__inner-circle,
          .mdc-radio__outer-circle {
            @include token-utils.create-token-slot(border-color, disabled-selected-icon-color);
            @include token-utils.create-token-slot(opacity, disabled-selected-icon-opacity);
          }
        }
      }
    }

    &:enabled {
      @include token-utils.use-tokens($tokens...) {
        &:not(:checked) + .mdc-radio__background .mdc-radio__outer-circle {
          @include token-utils.create-token-slot(border-color, unselected-icon-color);
        }

        &:checked + .mdc-radio__background {
          .mdc-radio__outer-circle,
          .mdc-radio__inner-circle {
            @include token-utils.create-token-slot(border-color, selected-icon-color);
          }
        }

        @if ($is-interactive) {
          &:focus:checked + .mdc-radio__background {
            .mdc-radio__inner-circle,
            .mdc-radio__outer-circle {
              @include token-utils.create-token-slot(border-color, selected-focus-icon-color);
            }
          }
        }
      }
    }

    &:checked + .mdc-radio__background .mdc-radio__inner-circle {
      transform: scale(0.5);
      transition: _enter-transition(transform), _enter-transition(border-color);
    }
  }

  @if ($is-interactive) {
    &.mat-mdc-radio-disabled-interactive .mdc-radio--disabled {
      pointer-events: auto;

      @include token-utils.use-tokens($tokens...) {
        .mdc-radio__native-control:not(:checked) + .mdc-radio__background .mdc-radio__outer-circle {
          @include token-utils.create-token-slot(border-color, disabled-unselected-icon-color);
          @include token-utils.create-token-slot(opacity, disabled-unselected-icon-opacity);
        }

        &:hover .mdc-radio__native-control:checked + .mdc-radio__background,
        .mdc-radio__native-control:checked:focus + .mdc-radio__background,
        .mdc-radio__native-control + .mdc-radio__background {
          .mdc-radio__inner-circle,
          .mdc-radio__outer-circle {
            @include token-utils.create-token-slot(border-color, disabled-selected-icon-color);
            @include token-utils.create-token-slot(opacity, disabled-selected-icon-opacity);
          }
        }
      }
    }
  }
}

// Conditionally disables the animations of the radio button.
@mixin radio-noop-animations() {
  &._mat-animation-noopable {
    .mdc-radio__background::before,
    .mdc-radio__outer-circle,
    .mdc-radio__inner-circle {
      // Needs to be `!important`, because MDC's selectors are really specific.
      transition: none !important;
    }
  }
}
