<template>
  <div id="search" @click="open" v-bind:class="{ active, ongoing }">
    <div id="input">
      <button
        v-if="active"
        class="action"
        @click="close"
        :aria-label="$t('buttons.close')"
        :title="$t('buttons.close')"
      >
        <i class="material-icons">arrow_back</i>
      </button>
      <i v-else class="material-icons">search</i>
      <input
        type="text"
        @keyup.exact="keyup"
        @keyup.enter="submit"
        ref="input"
        :autofocus="active"
        v-model.trim="value"
        :aria-label="$t('search.search')"
        :placeholder="$t('search.search')"
      />
    </div>

    <div id="result" ref="result">
      <div>
        <template v-if="isEmpty">
          <p>{{ text }}</p>

          <template v-if="value.length === 0">
            <div class="boxes">
              <h3>{{ $t("search.types") }}</h3>
              <div>
                <div
                  tabindex="0"
                  v-for="(v, k) in boxes"
                  :key="k"
                  role="button"
                  @click="init('type:' + k)"
                  :aria-label="$t('search.' + v.label)"
                >
                  <i class="material-icons">{{ v.icon }}</i>
                  <p>{{ $t("search." + v.label) }}</p>
                </div>
              </div>
            </div>
          </template>
        </template>
        <ul v-show="results.length > 0">
          <li v-for="(s, k) in filteredResults" :key="k">
            <router-link @click.native="close" :to="s.url">
              <i v-if="s.dir" class="material-icons">folder</i>
              <i v-else class="material-icons">insert_drive_file</i>
              <span>./{{ s.path }}</span>
            </router-link>
          </li>
        </ul>
      </div>
      <p id="renew">
        <i class="material-icons spin">autorenew</i>
      </p>
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations } from "vuex";
import url from "@/utils/url";
import { search } from "@/api";

var boxes = {
  image: { label: "images", icon: "insert_photo" },
  audio: { label: "music", icon: "volume_up" },
  video: { label: "video", icon: "movie" },
  pdf: { label: "pdf", icon: "picture_as_pdf" },
};

export default {
  name: "search",
  data: function () {
    return {
      value: "",
      active: false,
      ongoing: false,
      results: [],
      reload: false,
      resultsCount: 50,
      scrollable: null,
    };
  },
  watch: {
    show(val, old) {
      this.active = val === "search";

      if (old === "search" && !this.active) {
        if (this.reload) {
          this.setReload(true);
        }

        document.body.style.overflow = "auto";
        this.reset();
        this.value = "";
        this.active = false;
        this.$refs.input.blur();
      } else if (this.active) {
        this.reload = false;
        this.$refs.input.focus();
        document.body.style.overflow = "hidden";
      }
    },
    value() {
      if (this.results.length) {
        this.reset();
      }
    },
  },
  computed: {
    ...mapState(["user", "show"]),
    ...mapGetters(["isListing"]),
    boxes() {
      return boxes;
    },
    isEmpty() {
      return this.results.length === 0;
    },
    text() {
      if (this.ongoing) {
        return "";
      }

      return this.value === ""
        ? this.$t("search.typeToSearch")
        : this.$t("search.pressToSearch");
    },
    filteredResults() {
      return this.results.slice(0, this.resultsCount);
    },
  },
  mounted() {
    this.$refs.result.addEventListener("scroll", (event) => {
      if (
        event.target.offsetHeight + event.target.scrollTop >=
        event.target.scrollHeight - 100
      ) {
        this.resultsCount += 50;
      }
    });
  },
  methods: {
    ...mapMutations(["showHover", "closeHovers", "setReload"]),
    open() {
      this.showHover("search");
    },
    close(event) {
      event.stopPropagation();
      event.preventDefault();
      this.closeHovers();
    },
    keyup(event) {
      if (event.keyCode === 27) {
        this.close(event);
        return;
      }

      this.results.length = 0;
    },
    init(string) {
      this.value = `${string} `;
      this.$refs.input.focus();
    },
    reset() {
      this.ongoing = false;
      this.resultsCount = 50;
      this.results = [];
    },
    async submit(event) {
      event.preventDefault();

      if (this.value === "") {
        return;
      }

      let path = this.$route.path;
      if (!this.isListing) {
        path = url.removeLastDir(path) + "/";
      }

      this.ongoing = true;

      try {
        this.results = await search(path, this.value);
      } catch (error) {
        this.$showError(error);
      }

      this.ongoing = false;
    },
  },
};
</script>
