/**
 * @license
 * Copyright 2023 Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
//
// Copyright 2016 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

@use 'sass:map';
@use 'sass:math';
@use '@material/animation/functions' as mdc-animation;
@use '@material/animation/variables' as mdc-animation-variables;
@use '@material/density/functions' as mdc-density-functions;
@use '@material/feature-targeting/feature-targeting' as mdc-feature-targeting;
@use '@material/ripple/ripple' as mdc-ripple;
@use '@material/ripple/ripple-theme' as mdc-ripple-theme;
@use '@material/theme/theme-color' as mdc-theme-color;
@use '@material/theme/theme' as mdc-theme;
@use '@material/theme/color-custom-properties' as mdc-color-custom-properties;
@use '@material/theme/custom-properties' as mdc-custom-properties;
@use './checkbox-custom-properties';
@use './checkbox-theme';
@use '../theme';

///
/// Checkbox and ripple styles.
///
@mixin core-styles($query: mdc-feature-targeting.all()) {
  @include without-ripple($query);
  @include ripple-styles($query);

  // FORGE (new): adding our custom forge-specific styles
  @include forge-styles;
}

@mixin forge-styles() {
  .forge-checkbox {
    &--dense {
      // this goes from 0 (default) to -3. each -1 step from 0 reduces the size by 4px, i.e. -3 ends up being 28px
      @include checkbox-theme.density(-3);
    }

    &-wrapper--disabled {
      cursor: not-allowed;
  
      ::slotted(label) {
        cursor: not-allowed;
      }
    }
  }
  
  .mdc-checkbox {
    &--disabled + ::slotted(label) {
      @include theme.property(color, label-disabled-on-background);
    }
  }
}

/// Checkbox styles (Excluding ripple styles).
///
/// NOTE: This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
/// checkbox styles. It is recommended that most users use `mdc-checkbox-core-styles` instead.
// TODO(b/162887560): Rename to `checkbox-without-ripple-styles()`
@mixin without-ripple($query: mdc-feature-targeting.all()) {
  // TODO(b/165005345): Include theme-styles() after static-styles().
  @include theme-styles($query: $query);
  @include static-styles($query: $query);
}

/// Checkbox static styles.
/// Checkbox styles that are not customizable should go here.
@mixin static-styles($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-animation) {
    @include mark-keyframes_;
  }

  .mdc-checkbox {
    @include mdc-feature-targeting.targets($feat-structure) {
      @include base_;
    }
  }

  // Needed to disable hover effects on CSS-only (non-JS) checkboxes
  .mdc-checkbox--disabled {
    @include mdc-feature-targeting.targets($feat-structure) {
      @include disabled_;
    }
  }

  .mdc-checkbox__background {
    @include background_($query);
  }

  .mdc-checkbox__checkmark {
    @include checkmark_($query);
  }

  .mdc-checkbox__checkmark-path {
    @include checkmark-path_($query);
  }

  .mdc-checkbox__mixedmark {
    @include mixedmark_($query);
  }

  .mdc-checkbox--anim {
    @include mdc-feature-targeting.targets($feat-animation) {
      @include anim_;
    }
  }

  // FORGE (modify): use FORGE  state selectors due to Shadow DOM
  .forge-checkbox--checked .mdc-checkbox__background,
  .forge-checkbox--indeterminate .mdc-checkbox__background {
    @include mdc-feature-targeting.targets($feat-animation) {
      @include background--marked_;
    }

    .mdc-checkbox__checkmark-path {
      @include mdc-feature-targeting.targets($feat-structure) {
        @include checkmark-path--marked_;
      }
    }
  }

  // FORGE (modify): using slotted state selector due to Shadow DOM
  ::slotted(input[type='checkbox']) {
    @include mdc-feature-targeting.targets($feat-structure) {
      @include native-control_;
    }
  }

  // FORGE (modify): using slotted state selector due to Shadow DOM
  .forge-checkbox--disabled ::slotted(input[type='checkbox']) {
    @include mdc-feature-targeting.targets($feat-structure) {
      @include disabled_;
    }
  }

  // FORGE (modify): using class-based state selector due to Shadow DOM
  .forge-checkbox--checked .mdc-checkbox__background {
    .mdc-checkbox__checkmark {
      @include checkmark--checked_($query);
    }

    .mdc-checkbox__mixedmark {
      @include mdc-feature-targeting.targets($feat-structure) {
        @include mixedmark--checked_;
      }
    }
  }

  // FORGE (modify): using class-based state selector due to Shadow DOM
  .forge-checkbox--indeterminate .mdc-checkbox__background {
    .mdc-checkbox__checkmark {
      @include checkmark--indeterminate_($query);
    }

    .mdc-checkbox__mixedmark {
      @include mdc-feature-targeting.targets($feat-structure) {
        @include mixedmark--indeterminate_;
      }
    }
  }

  // JS checkbox
  .mdc-checkbox.mdc-checkbox--upgraded {
    .mdc-checkbox__background,
    .mdc-checkbox__checkmark,
    .mdc-checkbox__checkmark-path,
    .mdc-checkbox__mixedmark {
      @include mdc-feature-targeting.targets($feat-animation) {
        @include child--upgraded_;
      }
    }
  }
}

/// Checkbox theme styles.
/// Checkbox styles that are customizable should go here.
@mixin theme-styles($query: mdc-feature-targeting.all()) {
  .mdc-checkbox {
    @include checkbox-theme.theme(checkbox-theme.$base-theme, $query: $query);
  }
}

/// Checkbox's ripple styles.
///
/// NOTE: This API is intended for use by frameworks that may want to separate the ripple-related styles from the other
/// checkbox styles. It is recommended that most users use `mdc-checkbox-core-styles` instead.
@mixin ripple-styles($query: mdc-feature-targeting.all()) {
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-ripple.common($query); // COPYBARA_COMMENT_THIS_LINE

  .mdc-checkbox {
    @include mdc-ripple.surface($query: $query, $ripple-target: checkbox-theme.$ripple-target);
    @include mdc-ripple.radius-unbounded($query: $query, $ripple-target: checkbox-theme.$ripple-target);
    @include mdc-ripple-theme.behind-content(checkbox-theme.$ripple-target, $query: $query);
  }

  #{checkbox-theme.$ripple-target} {
    @include mdc-ripple.target-common($query: $query);
  }
}

@mixin base_ {
  display: inline-block;
  position: relative;
  flex: 0 0 checkbox-theme.$icon-size;
  box-sizing: content-box;
  width: checkbox-theme.$icon-size;
  height: checkbox-theme.$icon-size;
  line-height: 0;
  white-space: nowrap;
  cursor: pointer;
  vertical-align: bottom;
}

@mixin disabled_ {
  cursor: default;
  pointer-events: none;
}

@mixin child--upgraded_ {
  transition: none;
}

// Animation

@mixin anim_ {
  $mdc-checkbox-indeterminate-change-duration_: 500ms;

  // stylelint-disable selector-max-type

  &-unchecked-checked,
  &-unchecked-indeterminate,
  &-checked-unchecked,
  &-indeterminate-unchecked {
    .mdc-checkbox__background {
      animation-duration: checkbox-theme.$transition-duration * 2;
      animation-timing-function: linear;
    }
  }

  &-unchecked-checked {
    .mdc-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: mdc-checkbox-unchecked-checked-checkmark-path checkbox-theme.$transition-duration * 2 linear 0s;
      transition: none;
    }
  }

  &-unchecked-indeterminate {
    .mdc-checkbox__mixedmark {
      animation: mdc-checkbox-unchecked-indeterminate-mixedmark checkbox-theme.$transition-duration linear 0s;
      transition: none;
    }
  }

  &-checked-unchecked {
    .mdc-checkbox__checkmark-path {
      animation: mdc-checkbox-checked-unchecked-checkmark-path checkbox-theme.$transition-duration linear 0s;
      transition: none;
    }
  }

  &-checked-indeterminate {
    .mdc-checkbox__checkmark {
      animation: mdc-checkbox-checked-indeterminate-checkmark checkbox-theme.$transition-duration linear 0s;
      transition: none;
    }

    .mdc-checkbox__mixedmark {
      animation: mdc-checkbox-checked-indeterminate-mixedmark checkbox-theme.$transition-duration linear 0s;
      transition: none;
    }
  }

  &-indeterminate-checked {
    .mdc-checkbox__checkmark {
      animation: mdc-checkbox-indeterminate-checked-checkmark $mdc-checkbox-indeterminate-change-duration_ linear 0s;
      transition: none;
    }

    .mdc-checkbox__mixedmark {
      animation: mdc-checkbox-indeterminate-checked-mixedmark $mdc-checkbox-indeterminate-change-duration_ linear 0s;
      transition: none;
    }
  }

  &-indeterminate-unchecked {
    .mdc-checkbox__mixedmark {
      // stylelint-disable-next-line declaration-colon-space-after
      animation: mdc-checkbox-indeterminate-unchecked-mixedmark $mdc-checkbox-indeterminate-change-duration_ * 0.6 linear 0s;
      transition: none;
    }
  }

  // stylelint-enable selector-max-type
}

@mixin background_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);
  $feat-color: mdc-feature-targeting.create-target($query, color);

  @include mdc-feature-targeting.targets($feat-structure) {
    display: inline-flex;
    position: absolute;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: checkbox-theme.$icon-size;
    height: checkbox-theme.$icon-size;
    // border-color is overridden by the mdc-checkbox-unmarked-stroke-color() mixin
    border: checkbox-theme.$border-width solid currentColor;
    border-radius: 2px;
    background-color: transparent;
    pointer-events: none;
    will-change: background-color, border-color;
  }

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-exit(background-color), transition-exit(border-color);
  }
}

@mixin background--marked_ {
  transition: transition-enter(border-color), transition-enter(background-color);
}

// Native input

@mixin native-control_ {
  position: absolute;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: inherit;
}

// Check mark

@mixin checkmark_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-structure) {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    opacity: 0;
  }

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-exit(opacity, 0ms, checkbox-theme.$transition-duration * 2);
  }

  .mdc-checkbox--upgraded & {
    @include mdc-feature-targeting.targets($feat-structure) {
      opacity: 1;
    }
  }
}

@mixin checkmark--checked_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-enter(opacity, 0ms, checkbox-theme.$transition-duration * 2),
                transition-enter(transform, 0ms, checkbox-theme.$transition-duration * 2);
  }

  @include mdc-feature-targeting.targets($feat-structure) {
    opacity: 1;
  }
}

@mixin checkmark--indeterminate_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-structure) {
    transform: rotate(45deg);
    opacity: 0;
  }

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-exit(opacity, 0ms, checkbox-theme.$transition-duration),
                transition-exit(transform, 0ms, checkbox-theme.$transition-duration);
  }
}

// Check mark path

@mixin checkmark-path_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-exit(stroke-dashoffset, 0ms, checkbox-theme.$transition-duration * 2);
  }

  @include mdc-feature-targeting.targets($feat-structure) {
    stroke: currentColor;
    stroke-width: checkbox-theme.$mark-stroke-size * 1.3;
    stroke-dashoffset: $mark-path-length_;
    stroke-dasharray: $mark-path-length_;
  }
}

@mixin checkmark-path--marked_ {
  stroke-dashoffset: 0;
}

// Mixed mark

@mixin mixedmark_($query: mdc-feature-targeting.all()) {
  $feat-animation: mdc-feature-targeting.create-target($query, animation);
  $feat-structure: mdc-feature-targeting.create-target($query, structure);

  @include mdc-feature-targeting.targets($feat-structure) {
    width: 100%;
    height: 0;
    transform: scaleX(0) rotate(0deg);
    border-width: math.floor(checkbox-theme.$mark-stroke-size) * 0.5;
    border-style: solid;
    opacity: 0;
  }

  @include mdc-feature-targeting.targets($feat-animation) {
    transition: transition-exit(opacity), transition-exit(transform);
  }
}

@mixin mixedmark--checked_ {
  transform: scaleX(1) rotate(-45deg);
}

@mixin mixedmark--indeterminate_ {
  transform: scaleX(1) rotate(0deg);
  opacity: 1;
}

@function transition-enter($property, $delay: 0ms, $duration: checkbox-theme.$transition-duration) {
  @return mdc-animation.enter($property, $duration, $delay);
}

@function transition-exit($property, $delay: 0ms, $duration: checkbox-theme.$transition-duration) {
  @return mdc-animation.exit-temporary($property, $duration, $delay);
}

// Manual calculation done on SVG
$mark-path-length_: 29.7833385 !default;
$indeterminate-checked-easing-function_: cubic-bezier(0.14, 0, 0, 1) !default;

@mixin mark-keyframes_ {
  @keyframes mdc-checkbox-unchecked-checked-checkmark-path {
    0%,
    50% {
      stroke-dashoffset: $mark-path-length_;
    }

    50% {
      animation-timing-function: mdc-animation-variables.$deceleration-curve-timing-function;
    }

    100% {
      stroke-dashoffset: 0;
    }
  }

  @keyframes mdc-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);
    }
  }

  @keyframes mdc-checkbox-checked-unchecked-checkmark-path {
    from {
      animation-timing-function: mdc-animation-variables.$acceleration-curve-timing-function;
      opacity: 1;
      stroke-dashoffset: 0;
    }

    to {
      opacity: 0;
      stroke-dashoffset: $mark-path-length_ * -1;
    }
  }

  @keyframes mdc-checkbox-checked-indeterminate-checkmark {
    from {
      animation-timing-function: mdc-animation-variables.$deceleration-curve-timing-function;
      transform: rotate(0deg);
      opacity: 1;
    }

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

  @keyframes mdc-checkbox-indeterminate-checked-checkmark {
    from {
      animation-timing-function: $indeterminate-checked-easing-function_;
      transform: rotate(45deg);
      opacity: 0;
    }

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

  @keyframes mdc-checkbox-checked-indeterminate-mixedmark {
    from {
      animation-timing-function: mdc-animation-deceleration-curve-timing-function;
      transform: rotate(-45deg);
      opacity: 0;
    }

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

  @keyframes mdc-checkbox-indeterminate-checked-mixedmark {
    from {
      animation-timing-function: $indeterminate-checked-easing-function_;
      transform: rotate(0deg);
      opacity: 1;
    }

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

  @keyframes mdc-checkbox-indeterminate-unchecked-mixedmark {
    0% {
      animation-timing-function: linear;
      transform: scaleX(1);
      opacity: 1;
    }

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