/* Copyright (c) Fortanix, Inc.
|* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
|* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */

@use '../../../styling/defs.scss' as bk;

// Note: `$blur` should be in px, not rem (blur effect should be independent of any font size scaling)
@mixin dialog-backdrop($entry-dur: 200ms, $exit-dur: 180ms, $blur: 2px) {
  &::backdrop {
    transition-property: overlay, display, background-color, backdrop-filter;
    transition-timing-function: linear;
    transition-behavior: allow-discrete;
    
    // Open state styling
    background-color: light-dark(rgb(0 0 0 / 10%), rgb(0 0 0 / 20%));
    backdrop-filter: blur($blur) opacity(1);
    
    // Entry transition styling
    @media (prefers-reduced-motion: no-preference) { transition-duration: $entry-dur; }
    @starting-style {
      background-color: transparent;
      backdrop-filter: blur($blur) opacity(0);
    }
  }
  // Exit transition styling
  // Note: cannot nest the following inside `::backdrop`, since `:not()` needs to apply to the dialog not `::backdrop`
  &:not([open])::backdrop {
    transition-duration: 0ms;
    @supports (overlay: auto) { // Only in supported browsers
      @media (prefers-reduced-motion: no-preference) {
        transition-duration: $exit-dur;
      }
    }
    background-color: transparent;
    backdrop-filter: blur($blur) opacity(0);
  }
}

@mixin dialog-backdrop-opaque($entry-dur: 200ms, $exit-dur: 180ms) {
  &::backdrop {
    transition-property: overlay, display, background-color;
    transition-timing-function: linear;
    transition-behavior: allow-discrete;
    
    // Open state styling
    background-color: bk.$theme-page-default;
    
    // Entry transition styling
    @media (prefers-reduced-motion: no-preference) { transition-duration: $entry-dur; }
    @starting-style {
      background-color: transparent;
    }
  }
  // Exit transition styling
  // Note: cannot nest the following inside `::backdrop`, since `:not()` needs to apply to the dialog not `::backdrop`
  &:not([open])::backdrop {
    transition-duration: 0ms;
    @supports (overlay: auto) { // Only in supported browsers
      @media (prefers-reduced-motion: no-preference) {
        transition-duration: $exit-dur;
      }
    }
    background-color: transparent;
  }
}

@mixin dialog-fade-in($entry-dur: 200ms, $exit-dur: 180ms, $scale: 1) {
  transition-property: overlay, display, opacity, scale;
  transition-timing-function: ease-out;
  transition-behavior: allow-discrete;
  
  // Open state styling
  opacity: 1;
  scale: 1;
  
  // Entry transition styling
  @media (prefers-reduced-motion: no-preference) { transition-duration: $entry-dur; }
  @starting-style {
    opacity: 0;
    scale: $scale;
  }
  
  // Exit transition styling
  &:not([open]) {
    transition-duration: 0ms;
    @supports (overlay: auto) { // Only in supported browsers
      @media (prefers-reduced-motion: no-preference) {
        transition-duration: $exit-dur;
      }
    }
    transition-timing-function: ease-in;
    opacity: 0;
    scale: calc(1 - (($scale - 1) * 0.2)); // Multiply by 0.2 to make the scale out effect a bit more subtle
  }
}

@mixin dialog-slide-over($entry-dur: 200ms, $exit-dur: 180ms, $size: 0.8, $origin: right) {
  $dir: if($origin==right, 1, -1);
  
  transition-property: overlay, display, translate;
  transition-timing-function: ease-out;
  transition-behavior: allow-discrete;
  
  // Open state styling
  translate: 0;
  @if $origin == left {
    margin-inline-end: calc((1 - $size) * 100vi);
  } @else if $origin == right {
    margin-inline-start: calc((1 - $size) * 100vi);
  }
  
  // Entry transition styling
  @media (prefers-reduced-motion: no-preference) { transition-duration: $entry-dur; }
  @starting-style {
    translate: calc($dir * $size * 100vi) 0;
  }
  
  // Exit transition styling
  &:not([open]) {
    transition-duration: 0ms;
    @supports (overlay: auto) { // Only in supported browsers
      @media (prefers-reduced-motion: no-preference) {
        transition-duration: $exit-dur;
      }
    }
    transition-timing-function: ease-in;
    translate: calc($dir * $size * 100vi) 0;
  }
}


@layer baklava.components {
  .bk-dialog-modal {
    @include bk.component-base(bk-dialog-modal);
    
    --bk-dialog-modal-entry-dur: 200ms;
    --bk-dialog-modal-exit-dur: 120ms;
    --bk-dialog-modal-fade-scale: 1;
    
    // Basic modal positioning
    position: fixed;
    inset: 0;
    max-inline-size: 100vi;
    max-block-size: 100vb;
    
    // Modal backdrop
    &:not(.bk-dialog-modal--full-screen) {
      @include dialog-backdrop(
        $entry-dur: var(--bk-dialog-modal-entry-dur),
        $exit-dur: var(--bk-dialog-modal-exit-dur),
      );
    }
    
    
    // NOTE: added a workaround to fix the following inheritance issues, by using a portal to render modals 
    // 
    // The default `auto` inherits from the parent, which we do not want. In the future if `contain: user-select`
    // becomes supported, we could use that instead.
    //user-select: text;
    //cursor: default; // Unset in case parent element has a different `cursor`
    
    
    //
    // Display variants
    //
    
    &.bk-dialog-modal--center {
      margin: auto;
      inline-size: auto;
      block-size: fit-content;
      
      @include dialog-fade-in(
        $entry-dur: var(--bk-dialog-modal-entry-dur),
        $exit-dur: var(--bk-dialog-modal-exit-dur),
        $scale: var(--bk-dialog-modal-fade-scale),
      );
      
      --bk-dialog-modal-min-inset: #{bk.$spacing-2}; // Minimum amount to inset the modal by (on small screens)
      --bk-dialog-modal-size: 100ch;
      // Use margin for the width, so that the modal stretches up to the ideal size but also can shrink down
      margin-inline: clamp(var(--bk-dialog-modal-min-inset), 50% - (var(--bk-dialog-modal-size) / 2), 100svi);
      
      // The larger the viewport width (`vi`), the more breathing room in height (but up to `3lh` on large viewports)
      max-block-size: calc(100svb - clamp(var(--bk-dialog-modal-min-inset) * 2, 5vi, 3lh));
      
      &.bk-dialog-modal--small {
        --bk-dialog-modal-size: 60ch;
        --bk-dialog-modal-fade-scale: 1.05;
      }
      &.bk-dialog-modal--medium {
        --bk-dialog-modal-size: 100ch;
        --bk-dialog-modal-fade-scale: 1.04;
      }
      &.bk-dialog-modal--large {
        --bk-dialog-modal-size: 140ch;
        --bk-dialog-modal-fade-scale: 1.03;
      }
    }
    
    &.bk-dialog-modal--full-screen {
      // FIXME: test this on mobile for potential overflow/shifting. May need to use `dvb`/`dvi` instead?
      inset: 1rem;
      margin: 0;
      inline-size: auto;
      block-size: auto;
      
      --bk-dialog-modal-entry-dur: 120ms;
      --bk-dialog-modal-exit-dur: 120ms;
      @include dialog-fade-in(
        $entry-dur: var(--bk-dialog-modal-entry-dur),
        $exit-dur: var(--bk-dialog-modal-exit-dur),
      );
      
      @include dialog-backdrop-opaque(
        $entry-dur: var(--bk-dialog-modal-entry-dur),
        $exit-dur: var(--bk-dialog-modal-exit-dur),
      );
    }
    
    &.bk-dialog-modal--slide-over {
      inset: 0;
      margin: 0;
      inline-size: auto;
      block-size: auto;
      
      --bk-dialog-modal-slide-over-size: 0.8;
      &.bk-dialog-modal--small { --bk-dialog-modal-slide-over-size: 0.3; }
      &.bk-dialog-modal--medium { --bk-dialog-modal-slide-over-size: 0.5; }
      &.bk-dialog-modal--large { --bk-dialog-modal-slide-over-size: 0.8; }
      
      --bk-dialog-modal-entry-dur: 300ms;
      --bk-dialog-modal-exit-dur: 250ms;
      &.bk-dialog-modal--slide-over--left {
        @include dialog-slide-over(
          $entry-dur: var(--bk-dialog-modal-entry-dur),
          $exit-dur: var(--bk-dialog-modal-exit-dur),
          $size: var(--bk-dialog-modal-slide-over-size),
          $origin: left,
        );
      }
      &.bk-dialog-modal--slide-over--right {
        @include dialog-slide-over(
          $entry-dur: var(--bk-dialog-modal-entry-dur),
          $exit-dur: var(--bk-dialog-modal-exit-dur),
          $size: var(--bk-dialog-modal-slide-over-size),
          $origin: right,
        );
      }
    }
  }
}
