// Copyright 2017 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.

// stylelint-disable no-unknown-animations --
// Animations keyframes are included in `keyframes.scss`.
// stylelint-disable selector-class-pattern --
// Selector '.mdc-*' should only be used in this project.

@use 'sass:string';
@use '../animation/functions' as animation-functions;
@use '../dom/dom';
@use '../feature-targeting/feature-targeting';
@use '../rtl/rtl';
@use '../theme/theme';
@use '../theme/theme-color';
@use './variables';
@use './keyframes';

//
// Public
//

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

  @include feature-targeting.targets($feat-animation) {
    @include keyframes.primary-indeterminate-translate-keyframes_;
    @include keyframes.primary-indeterminate-scale-keyframes_;
    @include keyframes.secondary-indeterminate-translate-keyframes_;
    @include keyframes.secondary-indeterminate-scale-keyframes_;
    @include keyframes.buffering-keyframes_;
    @include keyframes.primary-indeterminate-translate-reverse-keyframes_;
    @include keyframes.secondary-indeterminate-translate-reverse-keyframes_;
    @include keyframes.buffering-reverse-keyframes_;
  }

  .mdc-linear-progress {
    @include feature-targeting.targets($feat-structure) {
      position: relative;
      width: 100%;
      transform: translateZ(0);
      // Create a border around the bar in Windows High Contrast Mode.
      outline: 1px solid transparent;
      overflow: hidden;

      @include dom.forced-colors-mode($exclude-ie11: true) {
        outline-color: CanvasText;
      }
    }

    @include feature-targeting.targets($feat-animation) {
      transition: animation-functions.exit-temporary(opacity, 250ms);
    }

    &__bar {
      @include feature-targeting.targets($feat-structure) {
        position: absolute;
        width: 100%;
        height: 100%;
        animation: none;
        transform-origin: top left;
      }

      @include feature-targeting.targets($feat-animation) {
        transition: animation-functions.exit-temporary(transform, 250ms);
      }
    }

    &__bar-inner {
      @include feature-targeting.targets($feat-structure) {
        display: inline-block;
        position: absolute;
        width: 100%;
        animation: none;
        // border-top is used rather than background-color to ensure that the
        // bar is visible in Windows High Contrast Mode.
        border-top-style: solid;
      }
    }

    &__buffer {
      @include feature-targeting.targets($feat-structure) {
        display: flex;
        position: absolute;
        width: 100%;
        height: 100%;
      }
    }

    &__buffer-dots {
      @include feature-targeting.targets($feat-structure) {
        background-repeat: repeat-x;
        // background-size: 10px variables.$height;
        flex: auto;
        transform: rotate(180deg);
      }

      @include feature-targeting.targets($feat-animation) {
        animation: mdc-linear-progress-buffering 250ms infinite linear;
      }
    }

    &__buffer-bar {
      @include feature-targeting.targets($feat-structure) {
        flex: 0 1 100%;
      }

      @include feature-targeting.targets($feat-animation) {
        transition: animation-functions.exit-temporary(flex-basis, 250ms);
      }
    }

    &__primary-bar {
      @include feature-targeting.targets($feat-structure) {
        transform: scaleX(0);
      }
    }

    &__secondary-bar {
      @include feature-targeting.targets($feat-structure) {
        display: none;
      }
    }

    @include indeterminate_($query: $query);

    @include rtl.rtl() {
      // The rtl() mixin does not account for nested `dir` attributes. Set
      // `dir` attribute on root to take highest priority.
      &:not([dir='ltr']) {
        @include _rtl-styles($query: $query);
      }
    }

    &--closed {
      @include feature-targeting.targets($feat-structure) {
        opacity: 0;
      }
    }

    &--closed-animation-off {
      .mdc-linear-progress__buffer-dots {
        @include feature-targeting.targets($feat-animation) {
          animation: none;
        }
      }

      &.mdc-linear-progress--indeterminate {
        .mdc-linear-progress__bar,
        .mdc-linear-progress__bar .mdc-linear-progress__bar-inner {
          @include feature-targeting.targets($feat-animation) {
            animation: none;
          }
        }
      }
    }
  }

  @at-root {
    @include bar-color(primary, $query: $query);
    @include buffer-color(variables.$baseline-buffer-color, $query: $query);
    @include track-height(variables.$height, $query: $query);
  }
}

@mixin bar-color($color, $query: feature-targeting.all()) {
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-linear-progress__bar-inner {
    @include feature-targeting.targets($feat-color) {
      // Border is used rather than background-color to ensure that the
      // bar is visible in Windows High Contrast Mode.
      @include theme.property(border-color, $color);
    }
  }
}

@mixin buffer-color($color, $query: feature-targeting.all()) {
  // We need to escape the '#' character as "%23" for SVG because '#' is a reserved character in URIs.
  $color-value-for-css: theme-color.prop-value($color);
  $color-value-for-svg: str-replace_(
    string.unquote('#{$color-value-for-css}'),
    '#',
    '%23'
  );
  $feat-color: feature-targeting.create-target($query, color);

  .mdc-linear-progress__buffer-dots {
    @include feature-targeting.targets($feat-color) {
      // SVG is optimized for data URI (https://codepen.io/tigt/post/optimizing-svgs-in-data-uris)
      // stylelint-disable-next-line function-url-quotes
      background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='#{$color-value-for-svg}'/%3E%3C/svg%3E");
    }
  }

  .mdc-linear-progress__buffer-bar {
    @include feature-targeting.targets($feat-color) {
      background-color: $color-value-for-css;
    }
  }
}

@mixin track-height($height, $query: feature-targeting.all()) {
  $feat-structure: feature-targeting.create-target($query, structure);
  .mdc-linear-progress {
    @include feature-targeting.targets($feat-structure) {
      height: $height;
    }

    &__bar-inner {
      @include feature-targeting.targets($feat-structure) {
        border-top-width: $height;
      }
    }

    &__buffer-dots {
      @include feature-targeting.targets($feat-structure) {
        background-size: 10px $height;
      }
    }
  }
}

//
// Private
//

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

  &--indeterminate {
    .mdc-linear-progress__bar {
      @include feature-targeting.targets($feat-structure) {
        transition: none;
      }
    }

    .mdc-linear-progress__primary-bar {
      @include feature-targeting.targets($feat-structure) {
        left: -145.166611%;
      }
    }

    .mdc-linear-progress__secondary-bar {
      @include feature-targeting.targets($feat-structure) {
        left: -54.888891%;
        display: block;
      }
    }

    &.mdc-linear-progress--animation-ready {
      .mdc-linear-progress__primary-bar {
        @include feature-targeting.targets($feat-animation) {
          animation: mdc-linear-progress-primary-indeterminate-translate 2s
            infinite linear;
        }

        > .mdc-linear-progress__bar-inner {
          @include feature-targeting.targets($feat-animation) {
            animation: mdc-linear-progress-primary-indeterminate-scale 2s
              infinite linear;
          }
        }
      }

      .mdc-linear-progress__secondary-bar {
        @include feature-targeting.targets($feat-animation) {
          animation: mdc-linear-progress-secondary-indeterminate-translate 2s
            infinite linear;
        }

        > .mdc-linear-progress__bar-inner {
          @include feature-targeting.targets($feat-animation) {
            animation: mdc-linear-progress-secondary-indeterminate-scale 2s
              infinite linear;
          }
        }
      }
    }
  }
}

@mixin _rtl-styles($query: $query) {
  $feat-structure: feature-targeting.create-target($query, structure);
  $feat-animation: feature-targeting.create-target($query, animation);

  .mdc-linear-progress__bar {
    @include feature-targeting.targets($feat-structure) {
      @include rtl.ignore-next-line();
      right: 0;
      @include rtl.ignore-next-line();
      -webkit-transform-origin: center right;
      @include rtl.ignore-next-line();
      transform-origin: center right;
    }
  }

  &.mdc-linear-progress--animation-ready {
    .mdc-linear-progress__primary-bar {
      @include feature-targeting.targets($feat-animation) {
        animation-name: mdc-linear-progress-primary-indeterminate-translate-reverse;
      }
    }

    .mdc-linear-progress__secondary-bar {
      @include feature-targeting.targets($feat-animation) {
        animation-name: mdc-linear-progress-secondary-indeterminate-translate-reverse;
      }
    }
  }

  .mdc-linear-progress__buffer-dots {
    @include feature-targeting.targets($feat-animation) {
      animation: mdc-linear-progress-buffering-reverse 250ms infinite linear;
    }

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

  &.mdc-linear-progress--indeterminate {
    .mdc-linear-progress__primary-bar {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.ignore-next-line();
        right: -145.166611%;
        @include rtl.ignore-next-line();
        left: auto;
      }
    }

    .mdc-linear-progress__secondary-bar {
      @include feature-targeting.targets($feat-structure) {
        @include rtl.ignore-next-line();
        right: -54.888891%;
        @include rtl.ignore-next-line();
        left: auto;
      }
    }
  }
}

// Based on https://css-tricks.com/snippets/sass/str-replace-function/
@function str-replace_($string, $search, $replace) {
  $index: string.index($string, $search);

  @if $index {
    $head: string.slice($string, 1, $index - 1);
    $tail: str-replace_(
      string.slice($string, $index + string.length($search)),
      $search,
      $replace
    );

    @return $head + $replace + $tail;
  }

  @return $string;
}
