@import '../core/theming/theming';
@import '../core/style/elevation';
@import '../core/style/variables';
@import '../core/ripple/ripple';


// The width/height of the checkbox element.
$md-checkbox-size: $md-toggle-size !default;
// The width of the line used to draw the checkmark / mixedmark.
$md-checkbox-mark-stroke-size: 2/15 * $md-checkbox-size !default;
// The width of the checkbox border shown when the checkbox is unchecked.
$md-checkbox-border-width: 2px;
// The base duration used for the majority of transitions for the checkbox.
$md-checkbox-transition-duration: 90ms;
// The amount of spacing between the checkbox and its label.
$md-checkbox-item-spacing: $md-toggle-padding;

// Manual calculation done on SVG
$_md-checkbox-mark-path-length: 22.910259;
$_md-checkbox-indeterminate-checked-easing-function: cubic-bezier(0.14, 0, 0, 1);

// The ripple size of the checkbox
$md-checkbox-ripple-size: 15px;

// Fades in the background of the checkbox when it goes from unchecked -> {checked,indeterminate}.
@keyframes md-checkbox-fade-in-background {
  0% {
    opacity: 0;
  }

  50% {
    opacity: 1;
  }
}

// Fades out the background of the checkbox when it goes from {checked,indeterminate} -> unchecked.
@keyframes md-checkbox-fade-out-background {
  0%, 50% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

// "Draws" in the checkmark when the checkbox goes from unchecked -> checked.
@keyframes md-checkbox-unchecked-checked-checkmark-path {
  0%, 50% {
    stroke-dashoffset: $_md-checkbox-mark-path-length;
  }

  50% {
    animation-timing-function: $md-linear-out-slow-in-timing-function;
  }

  100% {
    stroke-dashoffset: 0;
  }
}

// Horizontally expands the mixedmark when the checkbox goes from unchecked -> indeterminate.
@keyframes md-checkbox-unchecked-indeterminate-mixedmark {
  0%, 68.2% {
    transform: scaleX(0);
  }

  68.2% {
    animation-timing-function: cubic-bezier(0, 0, 0, 1);
  }

  100% {
    transform: scaleX(1);
  }
}

// "Erases" the checkmark when the checkbox goes from checked -> unchecked.
@keyframes md-checkbox-checked-unchecked-checkmark-path {
  from {
    animation-timing-function: $md-fast-out-linear-in-timing-function;
    stroke-dashoffset: 0;
  }

  to {
    stroke-dashoffset: $_md-checkbox-mark-path-length * -1;
  }
}


// Rotates and fades out the checkmark when the checkbox goes from checked -> indeterminate. This
// animation helps provide the illusion of the checkmark "morphing" into the mixedmark.
@keyframes md-checkbox-checked-indeterminate-checkmark {
  from {
    animation-timing-function: $md-linear-out-slow-in-timing-function;
    opacity: 1;
    transform: rotate(0deg);
  }

  to {
    opacity: 0;
    transform: rotate(45deg);
  }
}

// Rotates and fades the checkmark back into position when the checkbox goes from indeterminate ->
// checked. This animation helps provide the illusion that the mixedmark is "morphing" into the
// checkmark.
@keyframes md-checkbox-indeterminate-checked-checkmark {
  from {
    animation-timing-function: $_md-checkbox-indeterminate-checked-easing-function;
    opacity: 0;
    transform: rotate(45deg);
  }

  to {
    opacity: 1;
    transform: rotate(360deg);
  }
}

// Rotates and fades in the mixedmark when the checkbox goes from checked -> indeterminate. This
// animation, similar to md-checkbox-checked-indeterminate-checkmark, helps provide an illusion
// of "morphing" from checkmark -> mixedmark.
@keyframes md-checkbox-checked-indeterminate-mixedmark {
  from {
    animation-timing-function: $md-linear-out-slow-in-timing-function;
    opacity: 0;
    transform: rotate(-45deg);
  }

  to {
    opacity: 1;
    transform: rotate(0deg);
  }
}

// Rotates and fades out the mixedmark when the checkbox goes from indeterminate -> checked. This
// animation, similar to md-checkbox-indeterminate-checked-checkmark, helps provide an illusion
// of "morphing" from mixedmark -> checkmark.
@keyframes md-checkbox-indeterminate-checked-mixedmark {
  from {
    animation-timing-function: $_md-checkbox-indeterminate-checked-easing-function;
    opacity: 1;
    transform: rotate(0deg);
  }

  to {
    opacity: 0;
    transform: rotate(315deg);
  }
}


// Horizontally collapses and fades out the mixedmark when the checkbox goes from indeterminate ->
// unchecked.
@keyframes md-checkbox-indeterminate-unchecked-mixedmark {
  0% {
    animation-timing-function: linear;
    opacity: 1;
    transform: scaleX(1);
  }

  32.8%, 100% {
    opacity: 0;
    transform: scaleX(0);
  }
}

// Applied to elements that cover the checkbox's entire inner container.
%md-checkbox-cover-element {
  bottom: 0;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}

// Applied to elements that are considered "marks" within the checkbox, e.g. the checkmark and
// the mixedmark.
%md-checkbox-mark {
  $width-padding-inset: 2 * $md-checkbox-border-width;
  width: calc(100% - #{$width-padding-inset});
}

// Applied to elements that appear to make up the outer box of the checkmark, such as the frame
// that contains the border and the actual background element that contains the marks.
%md-checkbox-outer-box {
  @extend %md-checkbox-cover-element;
  border-radius: 2px;
  box-sizing: border-box;
  pointer-events: none;
}

md-checkbox {
  cursor: pointer;

  // Animation
  transition: background $swift-ease-out-duration $swift-ease-out-timing-function,
              md-elevation-transition-property-value();
}

.md-checkbox-layout {
  // `cursor: inherit` ensures that the wrapper element gets the same cursor as the md-checkbox
  // (e.g. pointer by default, regular when disabled), instead of the browser default.
  cursor: inherit;
  align-items: baseline;
  vertical-align: middle;
  display: inline-flex;
}

.md-checkbox-inner-container {
  display: inline-block;
  height: $md-checkbox-size;
  line-height: 0;
  margin: auto;
  margin-right: $md-checkbox-item-spacing;
  order: 0;
  position: relative;
  vertical-align: middle;
  white-space: nowrap;
  width: $md-checkbox-size;
  flex-shrink: 0;

  [dir='rtl'] & {
    margin: {
      left: $md-checkbox-item-spacing;
      right: auto;
    }
  }
}

// TODO(kara): Remove this style when fixing vertical baseline
.md-checkbox-layout .md-checkbox-label {
  line-height: 24px;
}

.md-checkbox-frame {
  @extend %md-checkbox-outer-box;

  background-color: transparent;
  border: $md-checkbox-border-width solid;
  transition: border-color $md-checkbox-transition-duration $md-linear-out-slow-in-timing-function;
  will-change: border-color;
}

.md-checkbox-background {
  @extend %md-checkbox-outer-box;

  align-items: center;
  display: inline-flex;
  justify-content: center;
  transition: background-color $md-checkbox-transition-duration
                  $md-linear-out-slow-in-timing-function,
              opacity $md-checkbox-transition-duration $md-linear-out-slow-in-timing-function;
  will-change: background-color, opacity;
}

.md-checkbox-checkmark {
  @extend %md-checkbox-cover-element;
  @extend %md-checkbox-mark;

  width: 100%;
}

.md-checkbox-checkmark-path {
  stroke: {
    dashoffset: $_md-checkbox-mark-path-length;
    dasharray: $_md-checkbox-mark-path-length;
    width: $md-checkbox-mark-stroke-size;
  }
}

.md-checkbox-mixedmark {
  @extend %md-checkbox-mark;

  height: floor($md-checkbox-mark-stroke-size);
  opacity: 0;
  transform: scaleX(0) rotate(0deg);
}

.md-checkbox-label-before {
  .md-checkbox-inner-container {
    order: 1;
    margin: {
      left: $md-checkbox-item-spacing;
      right: auto;
    }

    [dir='rtl'] & {
      margin: {
        left: auto;
        right: $md-checkbox-item-spacing;
      }
    }
  }
}

.md-checkbox-checked {
  .md-checkbox-checkmark {
    opacity: 1;
  }

  .md-checkbox-checkmark-path {
    stroke-dashoffset: 0;
  }

  .md-checkbox-mixedmark {
    transform: scaleX(1) rotate(-45deg);
  }
}

.md-checkbox-indeterminate {
  .md-checkbox-checkmark {
    opacity: 0;
    transform: rotate(45deg);
  }

  .md-checkbox-checkmark-path {
    stroke-dashoffset: 0;
  }

  .md-checkbox-mixedmark {
    opacity: 1;
    transform: scaleX(1) rotate(0deg);
  }
}


.md-checkbox-unchecked {
  .md-checkbox-background {
    background-color: transparent;
  }
}

.md-checkbox-disabled {
  cursor: default;
}

.md-checkbox-anim {
  $indeterminate-change-duration: 500ms;

  &-unchecked-checked {
    .md-checkbox-background {
      animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-in-background;
    }

    .md-checkbox-checkmark-path {
      // Instead of delaying the animation, we simply multiply its length by 2 and begin the
      // animation at 50% in order to prevent a flash of styles applied to a checked checkmark
      // as the background is fading in before the animation begins.
      animation:
        $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-unchecked-checked-checkmark-path;
    }
  }

  &-unchecked-indeterminate {
    .md-checkbox-background {
      animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-in-background;
    }

    .md-checkbox-mixedmark {
      animation:
        $md-checkbox-transition-duration linear 0ms md-checkbox-unchecked-indeterminate-mixedmark;
    }
  }

  &-checked-unchecked {
    .md-checkbox-background {
      animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-out-background;
    }

    .md-checkbox-checkmark-path {
      animation:
        $md-checkbox-transition-duration linear 0ms md-checkbox-checked-unchecked-checkmark-path;
    }
  }

  &-checked-indeterminate {
    .md-checkbox-checkmark {
      animation:
        $md-checkbox-transition-duration linear 0ms md-checkbox-checked-indeterminate-checkmark;
    }

    .md-checkbox-mixedmark {
      animation:
        $md-checkbox-transition-duration linear 0ms md-checkbox-checked-indeterminate-mixedmark;
    }
  }

  &-indeterminate-checked {
    .md-checkbox-checkmark {
      animation:
        $indeterminate-change-duration linear 0ms md-checkbox-indeterminate-checked-checkmark;
    }

    .md-checkbox-mixedmark {
      animation:
        $indeterminate-change-duration linear 0ms md-checkbox-indeterminate-checked-mixedmark;
    }
  }

  &-indeterminate-unchecked {
    .md-checkbox-background {
      animation: $md-checkbox-transition-duration * 2 linear 0ms md-checkbox-fade-out-background;
    }

    .md-checkbox-mixedmark {
      animation:
        $indeterminate-change-duration * 0.6 linear 0ms
        md-checkbox-indeterminate-unchecked-mixedmark;
    }
  }
}

.md-checkbox-input {
  // Move the input to the bottom and in the middle.
  // Visual improvement to properly show browser popups when being required.
  bottom: 0;
  left: 50%;
}

.md-checkbox-ripple {
  position: absolute;
  left: -$md-checkbox-ripple-size;
  top: -$md-checkbox-ripple-size;
  right: -$md-checkbox-ripple-size;
  bottom: -$md-checkbox-ripple-size;
  border-radius: 50%;
  z-index: 1;
  pointer-events: none;
}
