import { getDocument } from 'ssr-window';
import $ from '../../shared/dom7.js';
import { extend, deleteProps } from '../../shared/utils.js';
import Framework7Class from '../../shared/class.js';
import swipePanel from './swipe-panel.js';
import resizablePanel from './resizable-panel.js';
class Panel extends Framework7Class {
  constructor(app, params) {
    if (params === void 0) {
      params = {};
    }
    const extendedParams = extend({
      on: {}
    }, app.params.panel, params);
    super(extendedParams, [app]);
    const panel = this;
    panel.params = extendedParams;
    panel.$containerEl = panel.params.containerEl ? $(panel.params.containerEl).eq(0) : app.$el;
    panel.containerEl = panel.$containerEl[0];
    if (!panel.containerEl) {
      panel.$containerEl = app.$el;
      panel.containerEl = app.$el[0];
    }
    let $el;
    if (panel.params.el) {
      $el = $(panel.params.el).eq(0);
    } else if (panel.params.content) {
      $el = $(panel.params.content).filter(node => node.nodeType === 1).eq(0);
    }
    if ($el.length === 0) return panel;
    if ($el[0].f7Panel) return $el[0].f7Panel;
    $el[0].f7Panel = panel;
    let {
      side,
      effect,
      resizable
    } = panel.params;
    if (typeof side === 'undefined') side = $el.hasClass('panel-left') ? 'left' : 'right';
    if (typeof effect === 'undefined')
      // eslint-disable-next-line
      effect = $el.hasClass('panel-cover') ? 'cover' : $el.hasClass('panel-push') ? 'push' : $el.hasClass('panel-floating') ? 'floating' : 'reveal';
    if (typeof resizable === 'undefined') resizable = $el.hasClass('panel-resizable');
    let $backdropEl;
    if (panel.params.backdrop && panel.params.backdropEl) {
      $backdropEl = $(panel.params.backdropEl);
    } else if (panel.params.backdrop) {
      $backdropEl = panel.$containerEl.children('.panel-backdrop');
      if ($backdropEl.length === 0) {
        $backdropEl = $('<div class="panel-backdrop"></div>');
        panel.$containerEl.prepend($backdropEl);
      }
    }
    extend(panel, {
      app,
      side,
      effect,
      resizable,
      $el,
      el: $el[0],
      opened: false,
      $backdropEl,
      backdropEl: $backdropEl && $backdropEl[0]
    });

    // Install Modules
    panel.useModules();

    // Init
    panel.init();
    return panel;
  }
  getViewEl() {
    const panel = this;
    let viewEl;
    if (panel.$containerEl.children('.views').length > 0) {
      viewEl = panel.$containerEl.children('.views')[0];
    } else {
      viewEl = panel.$containerEl.children('.view')[0];
    }
    return viewEl;
  }
  setStateClasses(state) {
    const panel = this;
    const {
      side,
      el,
      effect
    } = panel;
    const viewEl = panel.getViewEl();
    const panelInView = viewEl && viewEl.contains(el);
    const $targetEl = !viewEl || panelInView ? panel.$containerEl : $('html');
    if (state === 'open') {
      $targetEl.addClass(`with-panel with-panel-${panel.side}-${panel.effect}`);
    }
    if (state === 'before-closing') {
      $targetEl.addClass('with-panel-closing');
    }
    if (state === 'closing') {
      $targetEl.addClass('with-panel-closing');
      $targetEl.removeClass(`with-panel with-panel-${panel.side}-${panel.effect}`);
    }
    if (state === 'after-closing') {
      $targetEl.removeClass('with-panel-closing');
    }
    if (state === 'closed') {
      $targetEl.removeClass(`with-panel-${side}-${effect}`);
    }
  }
  enableVisibleBreakpoint() {
    const panel = this;
    panel.visibleBreakpointDisabled = false;
    panel.setVisibleBreakpoint();
    return panel;
  }
  disableVisibleBreakpoint() {
    const panel = this;
    panel.visibleBreakpointDisabled = true;
    panel.setVisibleBreakpoint();
    return panel;
  }
  toggleVisibleBreakpoint() {
    const panel = this;
    panel.visibleBreakpointDisabled = !panel.visibleBreakpointDisabled;
    panel.setVisibleBreakpoint();
    return panel;
  }
  setVisibleBreakpoint(emitEvents) {
    if (emitEvents === void 0) {
      emitEvents = true;
    }
    const panel = this;
    const app = panel.app;
    if (!panel.visibleBreakpointResizeHandler) {
      panel.visibleBreakpointResizeHandler = function visibleBreakpointResizeHandler() {
        panel.setVisibleBreakpoint();
      };
      app.on('resize', panel.visibleBreakpointResizeHandler);
    }
    const {
      side,
      $el,
      $containerEl,
      params,
      visibleBreakpointDisabled
    } = panel;
    const breakpoint = params.visibleBreakpoint;
    const $viewEl = $(panel.getViewEl());
    const wasVisible = $el.hasClass('panel-in-breakpoint');
    if ($containerEl && $containerEl.hasClass('page')) {
      $viewEl.add($containerEl.children('.page-content, .tabs, .fab'));
    }
    if (app.width >= breakpoint && typeof breakpoint !== 'undefined' && breakpoint !== null && !visibleBreakpointDisabled) {
      if (!wasVisible) {
        panel.setStateClasses('closed');
        $el.addClass('panel-in-breakpoint').removeClass('panel-in panel-in-collapsed');
        panel.onOpen(false);
        panel.onOpened();
        $viewEl.css({
          [`margin-${side}`]: `${$el.width()}px`
        });
        app.allowPanelOpen = true;
        if (emitEvents) {
          panel.emit('local::breakpoint panelBreakpoint', panel);
          panel.$el.trigger('panel:breakpoint');
        }
      } else {
        $viewEl.css({
          [`margin-${side}`]: `${$el.width()}px`
        });
      }
    } else if (wasVisible) {
      $el.removeClass('panel-in-breakpoint panel-in');
      panel.onClose();
      panel.onClosed();
      $viewEl.css({
        [`margin-${side}`]: ''
      });
      if (emitEvents) {
        panel.emit('local::breakpoint panelBreakpoint', panel);
        panel.$el.trigger('panel:breakpoint');
      }
    }
  }
  enableCollapsedBreakpoint() {
    const panel = this;
    panel.collapsedBreakpointDisabled = false;
    panel.setCollapsedBreakpoint();
    return panel;
  }
  disableCollapsedBreakpoint() {
    const panel = this;
    panel.collapsedBreakpointDisabled = true;
    panel.setCollapsedBreakpoint();
    return panel;
  }
  toggleCollapsedBreakpoint() {
    const panel = this;
    panel.collapsedBreakpointDisabled = !panel.collapsedBreakpointDisabled;
    panel.setCollapsedBreakpoint();
    return panel;
  }
  setCollapsedBreakpoint(emitEvents) {
    if (emitEvents === void 0) {
      emitEvents = true;
    }
    const panel = this;
    const app = panel.app;
    if (!panel.collapsedBreakpointResizeHandler) {
      panel.collapsedBreakpointResizeHandler = function collapsedBreakpointResizeHandler() {
        panel.setCollapsedBreakpoint();
      };
      app.on('resize', panel.collapsedBreakpointResizeHandler);
    }
    const {
      $el,
      params,
      collapsedBreakpointDisabled
    } = panel;
    if ($el.hasClass('panel-in-breakpoint')) return;
    const breakpoint = params.collapsedBreakpoint;
    const wasVisible = $el.hasClass('panel-in-collapsed');
    if (app.width >= breakpoint && typeof breakpoint !== 'undefined' && breakpoint !== null && !collapsedBreakpointDisabled) {
      if (!wasVisible) {
        panel.setStateClasses('closed');
        $el.addClass('panel-in-collapsed').removeClass('panel-in');
        panel.collapsed = true;
        app.allowPanelOpen = true;
        if (emitEvents) {
          panel.emit('local::collapsedBreakpoint panelCollapsedBreakpoint', panel);
          panel.$el.trigger('panel:collapsedbreakpoint');
        }
      }
    } else if (wasVisible) {
      $el.removeClass('panel-in-collapsed panel-in');
      panel.collapsed = false;
      if (emitEvents) {
        panel.emit('local::collapsedBreakpoint panelCollapsedBreakpoint', panel);
        panel.$el.trigger('panel:collapsedbreakpoint');
      }
    }
  }
  enableResizable() {
    const panel = this;
    if (panel.resizableInitialized) {
      panel.resizable = true;
      panel.$el.addClass('panel-resizable');
    } else {
      resizablePanel(panel);
    }
    return panel;
  }
  disableResizable() {
    const panel = this;
    panel.resizable = false;
    panel.$el.removeClass('panel-resizable');
    return panel;
  }
  enableSwipe() {
    const panel = this;
    if (panel.swipeInitialized) {
      panel.swipeable = true;
    } else {
      swipePanel(panel);
    }
    return panel;
  }
  disableSwipe() {
    const panel = this;
    panel.swipeable = false;
    return panel;
  }
  onOpen(modifyHtmlClasses) {
    if (modifyHtmlClasses === void 0) {
      modifyHtmlClasses = true;
    }
    const panel = this;
    // eslint-disable-next-line
    panel._openTransitionStarted = false;
    const app = panel.app;
    panel.opened = true;
    app.panel.allowOpen = false;
    panel.$el.trigger('panel:beforeopen');
    panel.emit('local::beforeOpen panelBeforeOpen', panel);
    if (modifyHtmlClasses) {
      panel.setStateClasses('open');
    }
    panel.$el.trigger('panel:open');
    panel.emit('local::open panelOpen', panel);
  }
  onOpened() {
    const panel = this;
    const app = panel.app;
    app.panel.allowOpen = true;
    panel.$el.trigger('panel:opened');
    panel.emit('local::opened panelOpened', panel);
  }
  onClose() {
    const panel = this;
    const app = panel.app;
    panel.opened = false;
    app.panel.allowOpen = false;
    panel.$el.trigger('panel:beforeclose');
    panel.emit('local::beforeClose panelBeforeClose', panel);
    panel.setStateClasses('closing');
    panel.$el.trigger('panel:close');
    panel.emit('local::close panelClose', panel);
  }
  onClosed() {
    const panel = this;
    const app = panel.app;
    app.panel.allowOpen = true;
    panel.setStateClasses('after-closing');
    panel.$el.removeClass('panel-out');
    if (panel.$backdropEl) {
      const otherPanel = app.panel.get('.panel-in');
      const shouldHideBackdrop = !otherPanel || otherPanel && !otherPanel.$backdropEl;
      if (shouldHideBackdrop) {
        panel.$backdropEl.removeClass('panel-backdrop-in');
      }
    }
    panel.$el.trigger('panel:closed');
    panel.emit('local::closed panelClosed', panel);
  }
  toggle(animate) {
    if (animate === void 0) {
      animate = true;
    }
    const panel = this;
    const breakpoint = panel.params.visibleBreakpoint;
    const app = panel.app;
    if (app.width >= breakpoint && typeof breakpoint !== 'undefined' && breakpoint !== null) {
      return panel.toggleVisibleBreakpoint();
    }
    if (panel.opened) panel.close(animate);else panel.open(animate);
    return panel;
  }
  insertToRoot() {
    const panel = this;
    const document = getDocument();
    const {
      $el,
      $backdropEl,
      $containerEl
    } = panel;
    const $panelParentEl = $el.parent();
    const wasInDom = $el.parents(document).length > 0;
    if (!$panelParentEl.is($containerEl) || $el.prevAll('.views, .view').length) {
      const $insertBeforeEl = $containerEl.children('.panel, .views, .view').eq(0);
      const $insertAfterEl = $containerEl.children('.panel-backdrop').eq(0);
      if ($insertBeforeEl.length) {
        $el.insertBefore($insertBeforeEl);
      } else if ($insertAfterEl) {
        $el.insertBefore($insertAfterEl);
      } else {
        $containerEl.prepend($el);
      }
      if ($backdropEl && $backdropEl.length && (!$backdropEl.parent().is($containerEl) && $backdropEl.nextAll('.panel').length === 0 || $backdropEl.parent().is($containerEl) && $backdropEl.nextAll('.panel').length === 0)) {
        $backdropEl.insertBefore($el);
      }
      panel.once('panelClosed', () => {
        if (wasInDom) {
          $panelParentEl.append($el);
        } else {
          $el.remove();
        }
      });
    }
  }
  open(animate) {
    if (animate === void 0) {
      animate = true;
    }
    const panel = this;
    const app = panel.app;
    if (!app.panel.allowOpen) return false;
    const {
      effect,
      $el,
      $backdropEl,
      opened,
      $containerEl
    } = panel;
    if (!$el || $el.hasClass('panel-in')) {
      return panel;
    }
    panel.insertToRoot();

    // Ignore if opened
    if (opened || $el.hasClass('panel-in-breakpoint') || $el.hasClass('panel-in')) return false;

    // Close if some panel is opened
    const otherOpenedPanel = app.panel.get('.panel-in');
    if (otherOpenedPanel && otherOpenedPanel !== panel) {
      otherOpenedPanel.close(animate);
    }
    $el[animate ? 'removeClass' : 'addClass']('not-animated');
    $el.addClass('panel-in');
    if ($backdropEl) {
      $backdropEl.addClass('panel-backdrop-in');
      $backdropEl[animate ? 'removeClass' : 'addClass']('not-animated');
    }
    if (['cover', 'push', 'floating'].includes(panel.effect)) {
      /* eslint no-underscore-dangle: ["error", { "allow": ["_clientLeft"] }] */
      panel._clientLeft = $el[0].clientLeft;
    }

    // Transitionend
    const $viewEl = $(panel.getViewEl());
    if ($containerEl && $containerEl.hasClass('page')) {
      $viewEl.add($containerEl.children('.page-content, .tabs'));
    }
    const transitionEndTarget = effect === 'reveal' ? $viewEl : $el;
    function panelTransitionStart() {
      transitionEndTarget.transitionStart(() => {
        // eslint-disable-next-line
        panel._openTransitionStarted = true;
      });
    }
    function panelTransitionEnd() {
      transitionEndTarget.transitionEnd(e => {
        if ($(e.target).is(transitionEndTarget)) {
          if ($el.hasClass('panel-out')) {
            panel.onClosed();
          } else {
            panel.onOpened();
          }
        } else panelTransitionEnd();
      });
    }
    if (animate) {
      if ($backdropEl) {
        $backdropEl.removeClass('not-animated');
      }
      panelTransitionStart();
      panelTransitionEnd();
      $el.removeClass('panel-out not-animated').addClass('panel-in');
      panel.onOpen();
    } else {
      if ($backdropEl) {
        $backdropEl.addClass('not-animated');
      }
      $el.removeClass('panel-out').addClass('panel-in not-animated');
      panel.onOpen();
      panel.onOpened();
      // eslint-disable-next-line
      panel._openTransitionStarted = true;
    }
    return true;
  }
  close(animate) {
    if (animate === void 0) {
      animate = true;
    }
    const panel = this;
    const {
      effect,
      $el,
      $backdropEl,
      opened,
      $containerEl
    } = panel;
    if (!opened || $el.hasClass('panel-in-breakpoint') || !$el.hasClass('panel-in')) return panel;
    $el[animate ? 'removeClass' : 'addClass']('not-animated');
    if ($backdropEl) {
      $backdropEl[animate ? 'removeClass' : 'addClass']('not-animated');
    }
    const $viewEl = $(panel.getViewEl());
    if ($containerEl && $containerEl.hasClass('page')) {
      $viewEl.add($containerEl.children('.page-content, .tabs'));
    }
    const transitionEndTarget = effect === 'reveal' ? $viewEl : $el;
    // eslint-disable-next-line
    if (!panel._openTransitionStarted) {
      // eslint-disable-next-line
      animate = false;
    }
    function transitionEnd() {
      if ($el.hasClass('panel-out')) {
        panel.onClosed();
      } else if ($el.hasClass('panel-in')) {
        panel.onOpened();
      }
      panel.setStateClasses('after-closing');
    }
    if (animate) {
      transitionEndTarget.transitionEnd(() => {
        transitionEnd();
      });
      $el.removeClass('panel-in').addClass('panel-out');
      // Emit close
      panel.onClose();
    } else {
      $el.addClass('not-animated').removeClass('panel-in').addClass('panel-out');
      // Emit close
      panel.onClose();
      panel.onClosed();
    }
    return panel;
  }
  init() {
    const panel = this;
    // const app = panel.app;
    if (typeof panel.params.visibleBreakpoint !== 'undefined') {
      panel.setVisibleBreakpoint();
    }
    if (typeof panel.params.collapsedBreakpoint !== 'undefined') {
      panel.setCollapsedBreakpoint();
    }
    if (panel.params.swipe) {
      panel.enableSwipe();
    }
    if (panel.resizable) {
      panel.enableResizable();
    }
  }
  destroy() {
    let panel = this;
    const app = panel.app;
    const {
      $containerEl
    } = panel;
    if (!panel.$el) {
      // Panel already destroyed
      return;
    }
    panel.emit('local::beforeDestroy panelBeforeDestroy', panel);
    panel.$el.trigger('panel:beforedestroy');
    if (panel.visibleBreakpointResizeHandler) {
      app.off('resize', panel.visibleBreakpointResizeHandler);
    }
    if (panel.collapsedBreakpointResizeHandler) {
      app.off('resize', panel.collapsedBreakpointResizeHandler);
    }
    if (panel.$el.hasClass('panel-in-breakpoint') || panel.$el.hasClass('panel-in-collapsed')) {
      const $viewEl = $(panel.getViewEl());
      if ($containerEl && $containerEl.hasClass('page')) {
        $viewEl.add($containerEl.children('.page-content, .tabs'));
      }
      panel.$el.removeClass('panel-in-breakpoint panel-in-collapsed panel-in');
      $viewEl.css({
        [`margin-${panel.side}`]: ''
      });
      panel.emit('local::breakpoint panelBreakpoint', panel);
      panel.$el.trigger('panel:breakpoint');
    }
    panel.$el.trigger('panel:destroy');
    panel.emit('local::destroy panelDestroy', panel);
    if (panel.el) {
      panel.el.f7Panel = null;
      delete panel.el.f7Panel;
    }
    deleteProps(panel);
    panel = null;
  }
}
export default Panel;