import { Component, h, Prop, State, Element, Watch, Event } from '@stencil/core';
import { __ } from '@wordpress/i18n';
import { animateTo, stopAnimations } from '../../../functions/animate';
import { getAnimation, setDefaultAnimation } from '../../../functions/animation-registry';
import { lockBodyScrolling, unlockBodyScrolling } from '../../../functions/scroll';
export class ScDialog {
  constructor() {
    /** Indicates whether or not the dialog is open. You can use this in lieu of the show/hide methods. */
    this.open = false;
    /**
     * The dialog's label as displayed in the header. You should always include a relevant label even when using
     * `no-header`, as it is required for proper accessibility.
     */
    this.label = '';
    /**
     * Disables the header. This will also remove the default close button, so please ensure you provide an easy,
     * accessible way for users to dismiss the dialog.
     */
    this.noHeader = false;
    /** Does this have a footer */
    this.hasFooter = false;
  }
  /** Shows the dialog. */
  async show() {
    if (this.open) {
      return undefined;
    }
    this.open = true;
  }
  /** Hides the dialog */
  async hide() {
    if (!this.open) {
      return undefined;
    }
    this.open = false;
  }
  requestClose(source) {
    const slRequestClose = this.scRequestClose.emit(source);
    if (slRequestClose.defaultPrevented) {
      const animation = getAnimation(this.el, 'dialog.denyClose');
      animateTo(this.panel, animation.keyframes, animation.options);
      return;
    }
    this.hide();
  }
  handleKeyDown(event) {
    if (event.key === 'Escape') {
      event.stopPropagation();
      this.requestClose('keyboard');
    }
  }
  async handleOpenChange() {
    if (this.open) {
      // Show
      this.scShow.emit();
      lockBodyScrolling(this.el);
      // When the dialog is shown, Safari will attempt to set focus on whatever element has autofocus. This can cause
      // the dialogs's animation to jitter (if it starts offscreen), so we'll temporarily remove the attribute, call
      // `focus({ preventScroll: true })` ourselves, and add the attribute back afterwards.
      //
      // Related: https://github.com/shoelace-style/shoelace/issues/693
      //
      const autoFocusTarget = this.el.querySelector('[autofocus]');
      if (autoFocusTarget) {
        autoFocusTarget.removeAttribute('autofocus');
      }
      await Promise.all([stopAnimations(this.dialog), stopAnimations(this.overlay)]);
      this.dialog.hidden = false;
      // Set initial focus
      requestAnimationFrame(() => {
        const slInitialFocus = this.scInitialFocus.emit();
        if (!slInitialFocus.defaultPrevented) {
          // Set focus to the autofocus target and restore the attribute
          if (autoFocusTarget) {
            autoFocusTarget.focus({ preventScroll: true });
          }
          else {
            this.panel.focus({ preventScroll: true });
          }
        }
        // Restore the autofocus attribute
        if (autoFocusTarget) {
          autoFocusTarget.setAttribute('autofocus', '');
        }
      });
      const panelAnimation = getAnimation(this.el, 'dialog.show');
      const overlayAnimation = getAnimation(this.el, 'dialog.overlay.show');
      await Promise.all([animateTo(this.panel, panelAnimation.keyframes, panelAnimation.options), animateTo(this.overlay, overlayAnimation.keyframes, overlayAnimation.options)]);
      this.scAfterShow.emit();
    }
    else {
      // Hide
      this.scHide.emit();
      await Promise.all([stopAnimations(this.dialog), stopAnimations(this.overlay)]);
      const panelAnimation = getAnimation(this.el, 'dialog.hide');
      const overlayAnimation = getAnimation(this.el, 'dialog.overlay.hide');
      await Promise.all([animateTo(this.panel, panelAnimation.keyframes, panelAnimation.options), animateTo(this.overlay, overlayAnimation.keyframes, overlayAnimation.options)]);
      this.dialog.hidden = true;
      unlockBodyScrolling(this.el);
      // Restore focus to the original trigger
      const trigger = this.originalTrigger;
      if (typeof (trigger === null || trigger === void 0 ? void 0 : trigger.focus) === 'function') {
        setTimeout(() => trigger.focus());
      }
      this.scAfterHide.emit();
    }
  }
  componentDidLoad() {
    this.hasFooter = !!this.el.querySelector('[slot="footer"]');
    this.dialog.hidden = !this.open;
    if (this.open) {
      lockBodyScrolling(this.el);
    }
  }
  disconnectedCallback() {
    unlockBodyScrolling(this.el);
  }
  render() {
    return (h("div", { part: "base", ref: el => (this.dialog = el), class: {
        'dialog': true,
        'dialog--open': this.open,
        'dialog--has-footer': this.hasFooter,
      }, onKeyDown: e => this.handleKeyDown(e) },
      h("div", { part: "overlay", class: "dialog__overlay", onClick: () => this.requestClose('overlay'), ref: el => (this.overlay = el), tabindex: "-1" }),
      h("div", { part: "panel", class: "dialog__panel", role: "dialog", "aria-modal": "true", "aria-hidden": this.open ? 'false' : 'true', "aria-label": this.noHeader || this.label, "aria-labelledby": !this.noHeader || 'title', ref: el => (this.panel = el), tabindex: "0" },
        !this.noHeader && (h("header", { part: "header", class: "dialog__header" },
          h("h2", { part: "title", class: "dialog__title", id: "title" },
            h("slot", { name: "label" },
              " ",
              this.label.length > 0 ? this.label : String.fromCharCode(65279),
              " ")),
          h("sc-button", { class: "dialog__close", type: "text", circle: true, part: "close-button", exportparts: "base:close-button__base", onClick: () => this.requestClose('close-button') },
            h("sc-icon", { name: "x", label: __('Close', 'surecart') })))),
        h("div", { part: "body", class: "dialog__body" },
          h("slot", null)),
        h("footer", { part: "footer", class: "dialog__footer" },
          h("slot", { name: "footer" })))));
  }
  static get is() { return "sc-dialog"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["sc-dialog.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["sc-dialog.css"]
  }; }
  static get properties() { return {
    "open": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Indicates whether or not the dialog is open. You can use this in lieu of the show/hide methods."
      },
      "attribute": "open",
      "reflect": true,
      "defaultValue": "false"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The dialog's label as displayed in the header. You should always include a relevant label even when using\n`no-header`, as it is required for proper accessibility."
      },
      "attribute": "label",
      "reflect": true,
      "defaultValue": "''"
    },
    "noHeader": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Disables the header. This will also remove the default close button, so please ensure you provide an easy,\naccessible way for users to dismiss the dialog."
      },
      "attribute": "no-header",
      "reflect": true,
      "defaultValue": "false"
    }
  }; }
  static get states() { return {
    "hasFooter": {}
  }; }
  static get events() { return [{
      "method": "scRequestClose",
      "name": "scRequestClose",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Request close event"
      },
      "complexType": {
        "original": "'close-button' | 'keyboard' | 'overlay'",
        "resolved": "\"close-button\" | \"keyboard\" | \"overlay\"",
        "references": {}
      }
    }, {
      "method": "scShow",
      "name": "scShow",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scAfterShow",
      "name": "scAfterShow",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scHide",
      "name": "scHide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scAfterHide",
      "name": "scAfterHide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scInitialFocus",
      "name": "scInitialFocus",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }]; }
  static get elementRef() { return "el"; }
  static get watchers() { return [{
      "propName": "open",
      "methodName": "handleOpenChange"
    }]; }
}
setDefaultAnimation('dialog.show', {
  keyframes: [
    { opacity: 0, transform: 'scale(0.8)' },
    { opacity: 1, transform: 'scale(1)' },
  ],
  options: { duration: 150, easing: 'ease' },
});
setDefaultAnimation('dialog.hide', {
  keyframes: [
    { opacity: 1, transform: 'scale(1)' },
    { opacity: 0, transform: 'scale(0.8)' },
  ],
  options: { duration: 150, easing: 'ease' },
});
setDefaultAnimation('dialog.denyClose', {
  keyframes: [{ transform: 'scale(1)' }, { transform: 'scale(1.02)' }, { transform: 'scale(1)' }],
  options: { duration: 150 },
});
setDefaultAnimation('dialog.overlay.show', {
  keyframes: [{ opacity: 0 }, { opacity: 1 }],
  options: { duration: 150 },
});
setDefaultAnimation('dialog.overlay.hide', {
  keyframes: [{ opacity: 1 }, { opacity: 0 }],
  options: { duration: 150 },
});
