var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MapToComponentField, MapToComponentMethod } from 'vega-slimmer/core';
import { executeAfterTransition } from '../../../../utils/effect';
import ZIndexManager from '../../../../helpers/zindex/internal-vega-z-index-manager';
import { getCurrentBreakpoint } from '../../../../utils/breakpoints';
import ResponsiveFormatFacade from '../../../../helpers/formatter/responsive-map-formatter/responsive-format-facade';
import { PageResizeObserverSlimmer } from '../../../../helpers/slimmers/page-resize-observer-slimmer';
import { DomNodeSubjectObserverFactory } from '../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-observer-factory';
import { VegaInternalSidenavLinkClick } from '../../../../helpers/event-manager/event-id/vega-internal-event-id';
/** Manages the open status of a side navigation component, handling toggling, updating status based on screen size, and other related functionalities. */
export class VegaSidenavOpenStatusController extends PageResizeObserverSlimmer {
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-vega-resize-with-desktop}
   */
  /**
   * Register the callback function to page resize observer slimmer
   */
  constructor() {
    super({
      // eslint-disable-next-line jsdoc/require-jsdoc
      callback: /* istanbul ignore next */ () => {
        this.responsiveBehavior = this.getSidenavResponsiveBehavior();
        this.backdropController.updateBackdropAvailability(this.responsiveBehavior);
        this.updateOverflowAvailability();
        this.updateStatusOpenByDefault(true);
        this.collapseButtonRenderer.updateHandlerIconAvailability(this.canCollapseSidenav());
      },
    });
  }
  /* The below method is e2e-test covered in
   * @see{module:vega-sidenav-toggle-and-vegaStateUpdate}
   * @see{module:vega-sidenav-phone-call-toggle-method-change-position}
   */
  /* istanbul ignore next */
  /**
   * Toggle the open state of a side navigation based on certain conditions.
   */
  toggleSidenav() {
    if (this.canCollapseSidenav()) {
      switch (this.openState) {
        case 'open':
          this.setSideNavOpenStatus('clickClose');
          break;
        case 'close':
          this.setSideNavOpenStatus('clickOpen');
          break;
        case 'hoverOpen':
          this.setSideNavOpenStatus('hoverClose');
          break;
      }
    }
  }
  /**
   * The function `setSidenavRef` sets the sidebar reference.
   *
   * @param {HTMLDivElement} sidebarRef - A reference to the sidebar element in the HTML document.
   */
  setSidenavRef(sidebarRef) {
    this.sidebar = sidebarRef;
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-mouse-enter-and-mouse-leave-and-click}
   */
  /* istanbul ignore next */
  /**
   * Toggles the open/close status of a side navigation based on different input flags.
   *
   * @param {'hoverOpen' | 'hoverClose' | 'clickOpen' | 'clickClose'} statusFlag - A string literal type that can have one of the
   * following values: 'hoverOpen', 'hoverClose', 'clickOpen', or 'clickClose'.
   */
  setSideNavOpenStatus(statusFlag) {
    let updated = false;
    switch (statusFlag) {
      case 'clickOpen':
        if (this.openState === 'close') {
          this.openState = 'open';
          this.host.classList.add('open');
          this.sidebar.classList.add('open');
          updated = true;
        }
        break;
      case 'clickClose':
        if (this.openState === 'hoverOpen' || this.openState === 'open') {
          this.openState = 'close';
          this.host.classList.remove('open');
          this.sidebar.classList.remove('open');
          updated = true;
        }
        break;
      case 'hoverOpen':
        if (this.openState === 'close') {
          this.openState = 'hoverOpen';
          this.host.classList.add('open');
          this.sidebar.classList.add('open');
          updated = true;
        }
        break;
      case 'hoverClose':
        if (this.openState === 'hoverOpen') {
          this.openState = 'close';
          this.host.classList.remove('open');
          this.sidebar.classList.remove('open');
          updated = true;
        }
        break;
    }
    if (updated) {
      this.backdropController.updateBackdropAvailability(this.responsiveBehavior);
      this.updateOverflowAvailability();
      this.updateZIndex();
      this.stateUpdateEmitter.emit(this.openState);
    }
  }
  /**
   * Update the sidenav status when component did load
   */
  initOpenStatus() {
    this.responsiveBehavior = this.getSidenavResponsiveBehavior();
    this.updateStatusOpenByDefault();
  }
  /**
   * Update sidenav status when the property value change
   */
  updateOpenStatus() {
    this.updateStatusOpenByDefault();
    this.collapseButtonRenderer.updateHandlerIconAvailability(this.canCollapseSidenav());
  }
  /*
   * It will hide the sidenav when clicking the link in the sidenav on mobile terminal default.
   * If link set showSideBarOnClickLink is true that will don't hide the sidenav..
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-vega-click-handler-mobile}
   * @see{module:vega-sidenav-e2e-vega-click-handler-not-close-sidenav-mobile}
   */
  /* istanbul ignore next */
  /**
   * Add an observer to a DOM node for a specific event and handles the event payload to determine whether to close the sidebar.
   */
  registerSidenavLinkClickObserver() {
    DomNodeSubjectObserverFactory.addUniqueObserverToNode(this.host, VegaInternalSidenavLinkClick, (payload) => {
      // payload.detail = VegaSidenavLink.showSideBarOnClickLink
      if (!this.responsiveBehavior.showSideBarOnClickLink && !payload.detail) {
        this.setSideNavOpenStatus('clickClose');
      }
    });
  }
  /**
   * Remove the observer when the component remove from page
   */
  unregisterSidenavLinkClickObserver() {
    DomNodeSubjectObserverFactory.removeUniqueObserverFromNode(this.host, VegaInternalSidenavLinkClick);
  }
  /*
   * Please refer to the documentation for this part of the logic: vega-stencil/docs/sidenav-responsive-support-spec.md
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-vega-resize-with-desktop}
   */
  /* istanbul ignore next */
  /**
   * Returns different responsive behaviors based on the screen size.
   *
   * @returns {ResponsiveBehavior} Object
   */
  getSidenavResponsiveBehavior() {
    if (this.isLargeScreen()) {
      return {
        showSideBar: true,
        showBackdrop: false,
        canBeScrolled: true,
        showSideBarOnClickLink: true,
      };
    }
    else {
      return {
        showSideBar: false,
        showBackdrop: true,
        canBeScrolled: false,
        showSideBarOnClickLink: false,
      };
    }
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-z-index}
   * @see{module:vega-sidenav-e2e-z-index-in-mobile}
   */
  /* istanbul ignore next */
  /**
   * Set or remove the sidenav and backdrop style z-index
   */
  updateZIndex() {
    if (['hoverOpen', 'open'].includes(this.openState)) {
      this.backdropController.setZIndex('base');
      ZIndexManager.setZIndex(this.sidebar, 'base');
    }
    else {
      executeAfterTransition(() => {
        this.backdropController.removeZIndex('base');
        ZIndexManager.removeZIndex(this.sidebar, 'base');
      }, this.sidebar, 300);
    }
  }
  /**
   * Determines whether the sidenav can be collapsed based on the current open by default setting and screen size.
   *
   * @returns {boolean} The method `canCollapseSidenav()` returns a boolean value.
   */
  canCollapseSidenav() {
    const openByDefault = this.getCurrentOpenByDefault();
    return openByDefault !== 'disableCollapse' || !this.isLargeScreen();
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-vega-hidden-overflow-with-desktop-to-mobile}
   */
  /* istanbul ignore next */
  /**
   * Update the body style overflow
   */
  updateOverflowAvailability() {
    var _a;
    // eslint-disable-next-line no-restricted-globals
    const bodyElement = document.querySelector('body');
    if (!((_a = this.responsiveBehavior) === null || _a === void 0 ? void 0 : _a.canBeScrolled) && this.openState === 'open') {
      bodyElement.style['overflow'] = 'hidden';
    }
    else {
      bodyElement.style['overflow'] = null;
    }
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-sidenav-e2e-openByDefault-resize-screen-size}
   */
  /* istanbul ignore next */
  /**
   *
   *
   * @param triggerByResize
   */
  /**
   * Determines whether to open or close a side navigation based on certain conditions.
   *
   * @param {boolean} [triggerByResize=false] - The `updateStatusOpenByDefault` method was triggered by a resize event
   */
  updateStatusOpenByDefault(triggerByResize = false) {
    const openByDefault = this.getCurrentOpenByDefault();
    const canCollapseSidenav = this.canCollapseSidenav();
    if (!triggerByResize) {
      if (openByDefault == 'open' || !canCollapseSidenav) {
        this.setSideNavOpenStatus('clickOpen');
      }
      else if (openByDefault == 'close' ||
        (openByDefault == 'disableCollapse' && canCollapseSidenav)) {
        this.setSideNavOpenStatus('clickClose');
      }
    }
    else if (!canCollapseSidenav) {
      this.setSideNavOpenStatus('clickOpen');
    }
  }
  /**
   * Returns true if the current breakpoint is 'L' or 'XL'.
   *
   * @returns {boolean} Determine if the screen is considered large.
   */
  isLargeScreen() {
    const currentBreakpoint = getCurrentBreakpoint();
    return currentBreakpoint == 'L' || currentBreakpoint == 'XL';
  }
  /**
   * TReturns the current openByDefault value formatted using ResponsiveFormatFacade.
   *
   * @param {ResponsiveType<OpenByDefaultType>} input - parameter
   * @returns {OpenByDefaultType} The formatted value of the `input` parameter, which is of type `OpenByDefaultType`.
   */
  getCurrentOpenByDefault(input = this.openByDefault) {
    return ResponsiveFormatFacade.formatCustom(input);
  }
}
__decorate([
  MapToComponentField({ writable: true })
], VegaSidenavOpenStatusController.prototype, "openState", void 0);
__decorate([
  MapToComponentField()
], VegaSidenavOpenStatusController.prototype, "openByDefault", void 0);
__decorate([
  MapToComponentField()
], VegaSidenavOpenStatusController.prototype, "host", void 0);
__decorate([
  MapToComponentField()
], VegaSidenavOpenStatusController.prototype, "stateUpdateEmitter", void 0);
__decorate([
  MapToComponentField()
], VegaSidenavOpenStatusController.prototype, "backdropController", void 0);
__decorate([
  MapToComponentField()
], VegaSidenavOpenStatusController.prototype, "collapseButtonRenderer", void 0);
__decorate([
  MapToComponentMethod('componentDidLoad')
], VegaSidenavOpenStatusController.prototype, "initOpenStatus", null);
__decorate([
  MapToComponentMethod('watchOpenByDefaultChange')
], VegaSidenavOpenStatusController.prototype, "updateOpenStatus", null);
__decorate([
  MapToComponentMethod('connectedCallback')
], VegaSidenavOpenStatusController.prototype, "registerSidenavLinkClickObserver", null);
__decorate([
  MapToComponentMethod('disconnectedCallback')
], VegaSidenavOpenStatusController.prototype, "unregisterSidenavLinkClickObserver", null);
