@import '../core/style/variables';
@import '../core/ripple/ripple';
@import '../core/style/vendor-prefixes';
@import '../core/style/list-common';
@import '../../cdk/a11y/a11y';

$mat-slide-toggle-thumb-size: 20px !default;
$mat-slide-toggle-bar-border-radius: 8px !default;
$mat-slide-toggle-height: 24px !default;
$mat-slide-toggle-spacing: 8px !default;
$mat-slide-toggle-ripple-radius: 20px !default;
$mat-slide-toggle-bar-width: 36px !default;
$mat-slide-toggle-bar-height: 14px !default;
$mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-toggle-thumb-size;


.mat-slide-toggle {
  display: inline-block;
  height: $mat-slide-toggle-height;
  max-width: 100%;

  line-height: $mat-slide-toggle-height;
  white-space: nowrap;
  outline: none;

  // Disable user selection to ensure that dragging is smooth without grabbing
  // some elements accidentally.
  @include user-select(none);

  -webkit-tap-highlight-color: transparent;

  &.mat-checked {
    .mat-slide-toggle-thumb-container {
      transform: translate3d($mat-slide-toggle-bar-track-width, 0, 0);

      [dir='rtl'] & {
        transform: translate3d(-$mat-slide-toggle-bar-track-width, 0, 0);
      }
    }
  }

  &.mat-disabled {
    // The value is based on MDC.
    opacity: 0.38;

    .mat-slide-toggle-label, .mat-slide-toggle-thumb-container {
      cursor: default;
    }
  }
}

// The label element is our root container for the slide-toggle / switch indicator and label text.
// It has to be a label, to support accessibility for the visual hidden input.
.mat-slide-toggle-label {
  display: flex;
  flex: 1;
  flex-direction: row;
  align-items: center;
  height: inherit;

  cursor: pointer;
}

.mat-slide-toggle-content {
  @include mat-truncate-line();
}

/* If the label should be placed before the thumb then we just change the orders. */
.mat-slide-toggle-label-before {
  .mat-slide-toggle-label { order: 1; }
  .mat-slide-toggle-bar { order: 2; }
}

// Apply the margin for slide-toggles and revert it for RTL toggles with labelPosition before.
[dir='rtl'] .mat-slide-toggle-label-before .mat-slide-toggle-bar,
.mat-slide-toggle-bar {
  margin-right: $mat-slide-toggle-spacing;
  margin-left: 0;
}

// Switch the margins in RTL mode and also switch it if the labelPosition is set to before.
[dir='rtl'],
.mat-slide-toggle-label-before {
  .mat-slide-toggle-bar {
    margin-left: $mat-slide-toggle-spacing;
    margin-right: 0;
  }
}

.mat-slide-toggle-bar-no-side-margin {
  margin-left: 0;
  margin-right: 0;
}

// The thumb container is responsible for the dragging functionality.
// The container includes the visual thumb and the ripple container element.
.mat-slide-toggle-thumb-container {
  $thumb-bar-vertical-padding: ($mat-slide-toggle-thumb-size - $mat-slide-toggle-bar-height) / 2;

  position: absolute;
  z-index: 1;

  width: $mat-slide-toggle-thumb-size;
  height: $mat-slide-toggle-thumb-size;
  top: -$thumb-bar-vertical-padding;
  left: 0;

  transform: translate3d(0, 0, 0);
  transition: $swift-linear;
  transition-property: transform;

  @include cursor-grab;

  // Once the thumb container is being dragged around, we remove the transition duration to
  // make the drag feeling fast and not delayed.
  &.mat-dragging {
    transition-duration: 0ms;
  }

  &:active {
    @include cursor-grabbing;
  }

  ._mat-animation-noopable & {
    transition: none;
  }

  [dir='rtl'] & {
    left: auto;
    right: 0;
  }
}

// The visual thumb element that moves inside of the thumb bar.
// The parent thumb-container container is responsible for the movement of the visual thumb.
.mat-slide-toggle-thumb {
  height: $mat-slide-toggle-thumb-size;
  width: $mat-slide-toggle-thumb-size;
  border-radius: 50%;
}

// Horizontal bar for the slide-toggle.
// The slide-toggle bar is shown behind the movable thumb element.
.mat-slide-toggle-bar {
  position: relative;

  width: $mat-slide-toggle-bar-width;
  height: $mat-slide-toggle-bar-height;

  // Prevent shrinking of the bar container. It can happen that the content is long enough to
  // shrink the bar and the thumb.
  flex-shrink: 0;

  border-radius: $mat-slide-toggle-bar-border-radius;
}

// The slide toggle shows a visually hidden input inside of the component, which is used
// to take advantage of the native browser functionality.
.mat-slide-toggle-input {
  // Move the input to the bottom and in the middle of the thumb.
  // Visual improvement to properly show browser popups when being required.
  $horizontal-offset: $mat-slide-toggle-thumb-size / 2;

  bottom: 0;
  left: $horizontal-offset;

  [dir='rtl'] & {
    left: auto;
    right: $horizontal-offset;
  }
}

.mat-slide-toggle-bar,
.mat-slide-toggle-thumb {
  transition: $swift-linear;
  transition-property: background-color;
  transition-delay: 50ms;

  ._mat-animation-noopable & {
    transition: none;
  }
}

// Ripple positioning for the slide-toggle. Moves the ripple container into the center of the thumb.
// Increase specificity because ripple styles are part of the `mat-core` mixin and can
// potentially overwrite the absolute position of the container.
.mat-slide-toggle .mat-slide-toggle-ripple {
  position: absolute;
  top: calc(50% - #{$mat-slide-toggle-ripple-radius});
  left: calc(50% - #{$mat-slide-toggle-ripple-radius});
  height: $mat-slide-toggle-ripple-radius * 2;
  width: $mat-slide-toggle-ripple-radius * 2;
  z-index: 1;
  pointer-events: none;

  .mat-ripple-element:not(.mat-slide-toggle-persistent-ripple) {
    // Although the specs describe an opacity of 16% for ripples if the slide-toggle is being
    // pressed, we need to reduce the opacity a bit because besides the transient ripples,
    // the persistent ripple will still show up and blend with the transient ripple.
    opacity: 0.12;
  }
}

.mat-slide-toggle-persistent-ripple {
  width: 100%;
  height: 100%;
  transform: none;

  .mat-slide-toggle-bar:hover & {
    opacity: 0.04;
  }

  // As per specifications, the focus ripple should only show up if the slide-toggle has
  // been focused through keyboard. We cannot account for `cdk-program-focused` because clicking
  // on the label causes the focus origin to be `program` due to the focus redirection.
  .mat-slide-toggle:not(.mat-disabled).cdk-keyboard-focused & {
    opacity: 0.12;
  }

  // We do this here, rather than having a `:not(.mat-slide-toggle-disabled)`
  // above in the `:hover`, because the `:not` will bump the specificity
  // a lot and will cause it to overide the focus styles.
  &, .mat-slide-toggle.mat-disabled .mat-slide-toggle-bar:hover & {
    opacity: 0;
  }

  // Hover styles will be displayed after tapping on touch devices.
  // Disable the hover styling if the user's device doesn't support hovering.
  @media (hover: none) {
    // Note that we only negate the `:hover` rather than setting it to always be `display: none`,
    // in order to maintain the focus indication for hybrid touch + keyboard devices.
    .mat-slide-toggle-bar:hover & {
      display: none;
    }
  }
}

/** Custom styling to make the slide-toggle usable in high contrast mode. */
@include cdk-high-contrast() {
  .mat-slide-toggle-thumb {
    background: #fff;
    border: 1px solid #000;

    .mat-slide-toggle.mat-checked & {
      background: #000;
      border: 1px solid #fff;
    }
  }

  .mat-slide-toggle-bar {
    background: #fff;

    // As a focus indication in high contrast mode, we add a dotted outline to the slide-toggle
    // bar. Since the bar element does not have any padding, we need to specify an outline offset
    // because otherwise the opaque thumb element will hide the outline.
    .mat-slide-toggle.cdk-keyboard-focused & {
      outline: 1px dotted;
      outline-offset: ($mat-slide-toggle-height - $mat-slide-toggle-bar-height) / 2;
    }
  }
}

// Since the bar with a white background will be placed on a white background, we need to a black
// border in order to make sure that the bar is visible.
@include cdk-high-contrast(black-on-white) {
  .mat-slide-toggle-bar {
    border: 1px solid #000;
  }
}
