<template>
  <div class="dropdown">
    <button
      aria-haspopup="listbox"
      :aria-label="dropdown.label"
      :aria-expanded="visible"
      id="dropdownBtn"
      class="dropdown__button"
      ref="toggle"
      @click.stop.prevent="setSelected(dropdown.options[selector].value)"
      @keydown.enter.stop.prevent="setSelected(dropdown.options[selector].value)"
    >
      {{ selected }}
      <arrow-icon class="dropdown__arrow" :class="{ 'dropdown__arrow--open': visible }"></arrow-icon>
    </button>
    <ul
      tabindex="-1"
      role="listbox"
      aria-labelledby="dropdownBtn"
      :aria-activedescendant="descendant"
      class="dropdown__listbox"
      :class="{ 'dropdown__listbox--hidden': !visible }"
      ref="listbox"
      @keydown.down.stop.prevent="down"
      @keydown.up.stop.prevent="up"
      @keydown.esc.stop.prevent="setSelected(dropdown.options[selector].value)"
      @keydown.enter.stop.prevent="setSelected(dropdown.options[selector].value)"
    >
      <li
        v-for="(option, index) in dropdown.options"
        :key="`${option.value}_${index}`"
        :id="`${option.value}__${index}`"
        class="dropdown__listitem"
        :aria-selected="`${option.value}__${index}` === descendant"
        v-text="option.label"
        ref="option"
        role="option"
        @click.stop.prevent="setSelected(option.value, index)"
      >
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'dropdown',
  components: {
    ArrowIcon: () => import('@/components/icons/ArrowIcon.vue'),
  },
  props: {
    dropdown: {
      type: Object,
      required: true,
      validator: (val) => {
        const KEYS = ['label', 'options'];
        return KEYS.every((key) => val.hasOwnProperty(key));
      }
    },
    value: {
      required: true,
    }
  },
  data() {
    return {
      visible: false,
      selector: 0,
      scroll: 50,
    }
  },
  computed: {
    selected() {
      return this.value ? this.dropdown.options[this.selector].label : this.dropdown.label;
    },
    descendant() {
      return this.value ? `${this.dropdown.options[this.selector].value}__${this.selector}` : '';
    },
  },
  methods: {
    up() {
      if (this.selector === 0) {
        this.selector = this.dropdown.options.length - 1;
        this.$refs.listbox.scrollTop = (this.dropdown.options.length - 1) * this.scroll;
      } else {
        this.selector--;
        this.$refs.listbox.scrollTop -= this.scroll;
      }
    },
    down() {
      if (this.selector === this.dropdown.options.length - 1) {
        this.selector = 0;
        this.$refs.listbox.scrollTop = 0;
      } else {
        this.selector++;
        this.$refs.listbox.scrollTop += this.scroll;
      }
    },
    setSelected(val, index) {
      if (index || index === 0) {
        this.selector = index;
      }
      this.$emit('input', val);
      this.toggleListbox();
    },
    toggleListbox() {
      this.visible = !this.visible;
      if (this.visible) {
        this.$nextTick(() => {
          this.$refs.listbox.scrollTop = (this.selector * this.scroll);
          this.$refs.listbox.focus();
        });
      } else {
        this.$refs.toggle.focus();
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.dropdown {
  position: relative;
  width: 275px;
  width: 27.5rem;
  &__button {
    position: relative;
    width: 100%;
    height: 50px;
    height: 5rem;
    background-color: $white;
    border-radius: border-radius(primary);
    padding: 0px 30px 0px 15px;
    padding: 0rem 3rem 0rem 1.5rem;
    text-align: left;
    perspective: 800px;
    @include body-small(medium);
    &:focus {
      outline: auto;
      outline-color: $color-primary;
    }
    &:before {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      content: '';
      opacity: 1;
      transition: opacity transition(fast);
      box-shadow: box-shadow(tertiary);
    }
    &:after {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      content: '';
      opacity: 0;
      transition: opacity transition(fast);
      box-shadow: box-shadow(quaternary);
    }
    &:hover {
      &:before {
        opacity: 0;
      }
      &:after {
        opacity: 1;
      }
    }
  }
  &__arrow {
    position: absolute;
    top: 50%;
    right: 15px;
    transition: all transition(fast);
    transform: translateY(-50%) rotate3d(0, 0, 1, 180deg);
    &--open {
      transform: translateY(-50%) rotate3d(0, 0, 1, 360deg);
    }
  }
  &__listbox {
    list-style: none;
    padding-left: 0;
    margin-bottom: 0;
    position: absolute;
    top: 55px;
    left: 0;
    width: 100%;
    max-height: 150px;
    max-height: 15rem;
    overflow-y: scroll;
    background-color: $white;
    transition: opacity transition(fast);
    opacity: 1;
    box-shadow: box-shadow(quaternary);
    z-index: z-index(modal);
    &--hidden {
      opacity: 0;
      display: none;
    }
    &::-webkit-scrollbar {
      width: 10px;
      width: 1rem;
    }
    &::-webkit-scrollbar-thumb {
      border-radius: border-radius(secondary);
      background-color: $color-grey-septenary;
    }
  }
  &__listitem {
    display: block;
    width: 100%;
    height: 50px;
    height: 5rem;
    text-align: left;
    padding: 0px 15px;
    padding: 0rem 1.5rem;
    @include body-small(medium);
    line-height: 50px;
    line-height: 5rem;
    cursor: pointer;
    transition: all transition(fast);
    &:hover, &:focus, &[aria-selected] {
      background-color: $color-primary;
      color: $white;
    }
  }
}
</style>

