<template>
  <div class="label-selector">
    <input v-debounce:400ms="setQuery"
           class="search-field"
           ref="input"
           type="text"
           placeholder="Search...">
    <div class="filters">
      <span @click="resetHierarchyFilter"
            class="filter active">
        Show all
      </span>
      <span v-for="hierarchy in hierarchies"
            :key="hierarchy.key"
            @click="toggleHierarchyFilter(hierarchy.key)"
            :class="{active: isFilterActive(hierarchy.key)}"
            class="filter">
          {{ hierarchy.name }}
       </span>
    </div>
    <div class="labels">
      <div v-for="(label, index) in results"
           :key="index"
           @click="select(label)"
           class="label"
           :class="{selected: index === selectedIndex}"
           >


          <div class="name">
            <span v-html="highlight(label.name)"></span>
            <span v-if="label.hierarchy_level"
                  class="hierarchy">
              ({{ label.hierarchy_level }})
            </span>
          </div>
      </div>


      <div v-if="results.length < 1" class="label">
        No results found...
      </div>
    </div>
  </div>
</template>



<script>
export default {
  name: "label-selector",
  props: [
    "labels"
  ],
  mounted: function () {
    // register events to prevent global hotkeys while typing
    window.addEventListener('keypress', this.keypress, true);
    window.addEventListener('keydown', this.keypress, true);
    window.addEventListener('wheel', this.keypress, true);

    // focus text input
    this.$refs.input.focus();
  },
  destroyed: function () {
    window.removeEventListener('keypress', this.keypress, true);
    window.removeEventListener('keydown', this.keypress, true);
    window.removeEventListener('wheel', this.keypress, true);
  },
  data: function () {
    return {
      selectedIndex: 0,
      query: "",
      hierarchy_filters: [],
      deleteLabel: {
        hierarchy_level: null,
        identifier: null,
        name: 'None',
      },
    }
  },

  computed: {
    hierarchies: function() {
      let hierarchies = [...new Set(this.labels.map(l => l.hierarchy_level))]
      hierarchies.sort((a, b) => {
        if(a === null)
          return +1;
        if(b === null)
          return -1;
        if (a < b)
          return +1;
        else
          return -1;
      });
      return hierarchies.map(
        l => {
          return {
            key: l,
            name: (l === null ? "Art" : l)
          }
        }
      );
    },

    results: function() {
      const query = this.query;
      let labels = this.labels;
      const n_filters = this.hierarchy_filters.length;

      if (n_filters !== 0 && n_filters !== this.hierarchies.length)
        labels = labels.filter(
          l => this.hierarchy_filters.indexOf(l.hierarchy_level) > -1
        )

      labels = labels.filter(
        l => l.name.toLowerCase().indexOf(query) > -1
      );

      this.sort(labels);
      return [this.deleteLabel, ...labels];
    }
  },

  methods: {

    resetHierarchyFilter: function() {
      this.hierarchy_filters = [];
    },

    isFilterActive: function (key){
      return this.hierarchy_filters.length == 0 ||
        this.hierarchy_filters.indexOf(key) != -1;
    },

    toggleHierarchyFilter: function(key) {

      const idx = this.hierarchy_filters.indexOf(key);

      if (idx == -1)
        this.hierarchy_filters.push(key)
      else
        this.hierarchy_filters.splice(idx, 1)

      console.debug("Current hierarchy filters:",
        this.hierarchy_filters)
    },

    setQuery: function(query) {
      this.query = query.toLowerCase();
    },

    n_visible: function () {
      return this.results.length;
    },

    sort: function(labels) {
      labels.sort((a, b) => {

        if (a.hierarchy_level !== b.hierarchy_level) {
          if (a.hierarchy_level === null)
            return +1;
          if (b.hierarchy_level === null)
            return -1;
          if (a.hierarchy_level < b.hierarchy_level)
            return +1;
          else
            return -1;
        }

        if (a.name < b.name)
          return -1;
        else
          return +1;
      });
    },

    keypress: function (event) {
      event.stopPropagation();

      switch (event.key) {
        case 'ArrowDown':
          this.selectedIndex += 1;
          if (this.selectedIndex >= this.n_visible())
            this.selectedIndex = this.n_visible() - 1;
          break;

        case 'ArrowUp':
          this.selectedIndex -= 1;
          if (this.selectedIndex < 0)
            this.selectedIndex = 0;
          break;

        case 'Enter':
          this.select(this.results[this.selectedIndex]);
          break;

        case 'Escape':
          this.closeDelayed();
          break;

        default:
          this.selectedIndex = Math.min(1, this.n_visible() - 1);
          break;
      }
    },

    highlight: function (name) {
      const query = this.query
      if (!query)
        return name;

      const start = name.toLowerCase().indexOf(query);
      if (start == -1)
        return name

      const end = start + query.length;

      const pre = name.substring(0, start);
      const match = name.substring(start, end);
      const post = name.substring(end);
      return `${pre}<strong>${match}</strong>${post}`;
    },

    select: function (label) {
      console.debug("selected label", label);
      this.$emit('label', label);
      this.closeDelayed();
    },

    closeDelayed: function () {
      setTimeout(() => this.$emit('close', true), 100);
    },
  }
}
</script>


<style scoped>

.label-selector {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 101;

  width: 30rem;
  max-width: 90vw;
  max-height: 90%;

  display: flex;
  flex-direction: column;

  border-bottom-right-radius: 0.5rem;
  border-bottom-left-radius: 0.5rem;
  padding: 1rem;

  background-color: rgba(0, 0, 0, 0.75);
  color: whitesmoke;

  animation: label-selector-animation 0.3s ease-out forwards;

  box-shadow: 10px 10px 20px 10px rgba(0, 0, 0, 0.4);

}

@keyframes label-selector-animation {
  from {
    transform: translateX(-50%) translateY(-100%);
  }
  to {
    transform: translateX(-50%) translateY(0%);
  }
}

input {
  margin-bottom: 0.5rem;
  padding: 0.5rem;
  border-radius: 0.5rem;
  border: 0px;
}

.labels {
  flex-grow: 1;
  overflow: auto;
}

.label {
  padding: 0.25rem 0.5rem;
  cursor: pointer;
  border-radius: 0.3rem;
  margin: 0.2rem;
}

.label:not(:last-child) {
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}

.label:hover, .label.selected {
  background-color: var(--primary);
}

.hierarchy {
  font-size: 77%;
  opacity: 0.8;
  float: right;
}

.filters {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  align-items: baseline;
  padding: 0.25rem;
  margin-bottom: 0.25rem;
  border-bottom: 2px solid rgba(255, 255, 255, 0.2);
}

.filter {
  flex-grow: 1;
  border-radius: 0.5rem;
  margin: 0rem 0.5rem;
  padding: 0.25rem;
  text-align: center;

  background-color: rgb(50%, 50%, 50%);
  border: 1px solid rgb(10%,10%,10%);
  color: rgb(20%, 20%, 20%);
  cursor: pointer;
}

.filter.active {
  background-color: rgb(25%, 25%, 25%);
  color: whitesmoke;
}

.filter:hover {
  background-color: rgb(40%, 40%, 40%);
}

.filter.active:hover {
  background-color: rgb(20%, 20%, 20%);
}

</style>
