@import '../core/style/variables';
@import '../core/style/noop-animation';


// Animation config
$mat-progress-spinner-stroke-rotate-fallback-duration: 10 * 1000ms !default;
$mat-progress-spinner-stroke-rotate-fallback-ease: cubic-bezier(0.87, 0.03, 0.33, 1) !default;

$_mat-progress-spinner-default-radius: 45px;
$_mat-progress-spinner-default-circumference: $pi * $_mat-progress-spinner-default-radius * 2;

.mat-progress-spinner {
  display: block;
  position: relative;

  svg {
    position: absolute;
    transform: rotate(-90deg);
    top: 0;
    left: 0;
    transform-origin: center;
    overflow: visible;
  }

  circle {
    @include _noop-animation();
    fill: transparent;
    transform-origin: center;
    transition: stroke-dashoffset 225ms linear;
  }

  &.mat-progress-spinner-indeterminate-animation[mode='indeterminate'] {
    @include _noop-animation();
    animation: mat-progress-spinner-linear-rotate $swift-ease-in-out-duration * 4
        linear infinite;

    circle {
      @include _noop-animation();
      transition-property: stroke;
      // Note: we multiply the duration by 8, because the animation is spread out in 8 stages.
      animation-duration: $swift-ease-in-out-duration * 8;
      animation-timing-function: $ease-in-out-curve-function;
      animation-iteration-count: infinite;
    }
  }

  &.mat-progress-spinner-indeterminate-fallback-animation[mode='indeterminate'] {
    @include _noop-animation();
    animation: mat-progress-spinner-stroke-rotate-fallback
               $mat-progress-spinner-stroke-rotate-fallback-duration
               $mat-progress-spinner-stroke-rotate-fallback-ease
               infinite;

    circle {
      @include _noop-animation();
      transition-property: stroke;
    }
  }
}


// Animations for indeterminate mode
@keyframes mat-progress-spinner-linear-rotate {
  0%       { transform: rotate(0deg); }
  100%     { transform: rotate(360deg); }
}

@at-root {
  $start: (1 - 0.05) * $_mat-progress-spinner-default-circumference; // start the animation at 5%
  $end: (1 - 0.8) * $_mat-progress-spinner-default-circumference; // end the animation at 80%
  $fallback-iterations: 4;

  @keyframes mat-progress-spinner-stroke-rotate-100 {
    /*
      stylelint-disable declaration-block-single-line-max-declarations,
        declaration-block-semicolon-space-after
    */

    // .0001 percentage difference is necessary in order to avoid unwanted animation frames
    // for example because the animation duration is 4 seconds, .1% accounts to 4ms
    // which are enough to see the flicker described in
    // https://github.com/angular/components/issues/8984
    //
    // NOTE: this is replaced by js for any diameter other that 100
    0%      { stroke-dashoffset: $start;  transform: rotate(0); }
    12.5%   { stroke-dashoffset: $end;    transform: rotate(0); }
    12.5001%  { stroke-dashoffset: $end;    transform: rotateX(180deg) rotate(72.5deg); }
    25%     { stroke-dashoffset: $start;  transform: rotateX(180deg) rotate(72.5deg); }

    25.0001%   { stroke-dashoffset: $start;  transform: rotate(270deg); }
    37.5%   { stroke-dashoffset: $end;    transform: rotate(270deg); }
    37.5001%  { stroke-dashoffset: $end;    transform: rotateX(180deg) rotate(161.5deg); }
    50%     { stroke-dashoffset: $start;  transform: rotateX(180deg) rotate(161.5deg); }

    50.0001%  { stroke-dashoffset: $start;  transform: rotate(180deg); }
    62.5%   { stroke-dashoffset: $end;    transform: rotate(180deg); }
    62.5001%  { stroke-dashoffset: $end;    transform: rotateX(180deg) rotate(251.5deg); }
    75%     { stroke-dashoffset: $start;  transform: rotateX(180deg) rotate(251.5deg); }

    75.0001%  { stroke-dashoffset: $start;  transform: rotate(90deg); }
    87.5%   { stroke-dashoffset: $end;    transform: rotate(90deg); }
    87.5001%  { stroke-dashoffset: $end;    transform: rotateX(180deg) rotate(341.5deg); }
    100%    { stroke-dashoffset: $start;  transform: rotateX(180deg) rotate(341.5deg); }
    // stylelint-enable
  }

  // For IE11 and Edge, we fall back to simply rotating the spinner because
  // animating stroke-dashoffset is not supported. The fallback uses multiple
  // iterations to vary where the spin "lands".
  @keyframes mat-progress-spinner-stroke-rotate-fallback {
    @for $i from 0 through $fallback-iterations {
      $percent: 100 / $fallback-iterations * $i;
      $offset: 360 / $fallback-iterations;
      #{$percent}% { transform: rotate(#{$i * (360 * 3 + $offset)}deg); }
    }
  }
}
