<template>
  <div :class="['panel', { open: open }]">
    <TfButton
      class="close-btn"
      type="primary"
      icon="times"
      size="icon-no-fill"
      no-border
      @click="closePanel"
    >
      Close Panel
    </TfButton>
    <slot />
  </div>
</template>

<script>
  export default {
    name: 'TfPanel',
    props: {
      backUrl: {
        type: String, // this is the url that we look for to trigger this panel
        default: null,
      },
      open: {
        type: Boolean,
        default: false,
      },
      action: {
        type: String,
        default: null,
      },
    },
    created() {
      document.addEventListener('keyup', this.escapeKeyListener);
      document.addEventListener('click', this.outsidePanelListener);
    },
    destroyed() {
      document.removeEventListener('keyup', this.escapeKeyListener);
      document.removeEventListener('click', this.outsidePanelListener);
    },
    methods: {
      /**
       * Close the panel if the user hits the esc key.
       *
       * @param {event} event
       * @param {number} event.keyCode
       */
      escapeKeyListener({ keyCode }) {
        if (keyCode === 27) {
          this.closePanel();
        }
      },

      /**
       * Close the panel when when someone clicks outside the panel.
       *
       * @param {event} event
       * @param {object} event.target
       */
      outsidePanelListener({ target }) {
        const panel = this.$el;
        const isInPanel = panel === target || panel.contains(target);
        const dontClosePanel = this.shouldNotClosePanel(target);
        const hasTextSelection = getSelection() && getSelection().toString().length > 0;

        if (!isInPanel && !dontClosePanel && !hasTextSelection && this.open) {
          this.closePanel();
        }
      },

      /**
       * Close the panel.
       * Replacing the route would throw an error since it's a duplicate identical route
       * If this happens, we are probably opening the panel via a dispatch
       * and should close it the same way.
       */
      closePanel() {
        if (this.backUrl === this.$route.path) {
          this.$store.dispatch(this.action, false);
        } else {
          this.$router.replace(this.backUrl);
        }
      },

      /**
       * Check if the user clicked on something that should not close the panel.
       * This include even if it's outside the panel.
       *
       * @param {object} element
       * @returns {boolean}
       */
      shouldNotClosePanel(element) {
        if (
          element.hasAttribute
          && (
            element.hasAttribute('data-dont-close-panel')
            || element.hasAttribute('data-do-not-close-panel')
          )
        ) {
          return true;
        }
        return element.parentNode && this.shouldNotClosePanel(element.parentNode);
      },
    },
  };
</script>
<style lang="scss" scoped>
@import 'src/assets/styles/mixins';

.panel {
  position: fixed;
  right: 0;
  z-index: 100;
  height: 100%;
  width: 0;
  transition: width .5s;
  max-width: 557px;
  box-sizing: border-box;
  background: $tf-white;
  box-shadow: 0 0 6px 0 rgba($tf-black, .04), 0 2px 4px 0 rgba($tf-black, .12);
  border: solid 1px $tf-extra-light-gray-1;
  color: $tf-black;
  text-align: center;
  overflow-y: auto;
  overflow-x: hidden;
  -ms-overflow-style: -ms-autohiding-scrollbar;

  &.open {
    width: 100%;
  }

  .close-btn {
    position: absolute;
    right: 9px;
    top: 9px;
  }
}
</style>
