<template>
  <div :class="['search__outer', {'light': light}]">
    <!-- Label -->
    <label :class="['search__label', {'dirty': dirty}]">
      {{ label }}
    </label>
    <!-- inner -->
    <div :class="['search__inner', {'focus': focus}]">
      <!-- Input -->
      <input
        v-model="value"
        :label="label"
        :placeholder="placeholder"
        :class="['search__input', {'invalid' : error}]"
        :focus="focus"
        @focus="handleFocus(value);"
        @input="handleInput(value);"
        @change="handleChange(value)"
        @blur="handleBlur();"
        @keydown.enter="handleEnter(value)"
        @keydown.down="down"
        @keydown.up="up">
      <span class="search__suggestion">
        {{ suggest }}
      </span>
      <i class="search__icon material-icons">
        keyboard_arrow_down
      </i>
    </div>
    <!-- Menu -->
    <ul
      :class="['search__menu', {'visible': isOpen}]">
      <li
        v-for="(result, index) in searchResults"
        :key="index"
        tab-index="0"
        :class="['search__option', {'highlighted' : highlightIndex === index}]"
        @mouseover="highlightIndex = index"
        @click="suggestionSelected(searchResults[highlightIndex])">
        {{ result }}
      </li>
    </ul>
    <!-- / Menu -->
  </div>
</template>
<script>
import { setTimeout } from "timers";

export default {
  name: "BaseSearch",
  model: {
    prop: "focus",
    event: "change"
  },
  props: {
    options: {
      type: Array,
      default: Array
    },
    suffix: {
      type: String,
      default: null
    },
    label: {
      type: String,
      default: null
    },
    placeholder: {
      type: String,
      default: null
    },
    light: {
      type: Boolean,
      default: false
    },
    explicit: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      value: "",
      focus: false,
      error: false,
      filled: false,
      isOpen: false,
      highlightIndex: -1
    };
  },
  computed: {
    dirty() {
      if (this.focus === true || this.value !== "" || this.placeholder)
        return true;
      return false;
    },
    searchResults() {
      const input = this.value;
      // filter options on input
      const results = this.options.filter(option => {
        return option.includes(input);
      });

      return results;
    },

    // Suggestion rules
    beginsWith() {
      // does suggestion begin with search value?
      if (this.suggestion) {
        return this.suggestion.startsWith(this.value);
      }
      return false;
    },
    isValid() {
      // If search value doesn't have to be within options, everything is okay
      if (this.explicit) return true;
      return this.options.includes(this.value);
    },
    suggest() {
      // Determine whetther or not to show suggestion
      if (this.beginsWith === true && this.focus === true)
        return this.suggestion;
      return "";
    },
    suggestion() {
      // Actual suggestion
      return this.searchResults[this.highlightIndex];
    }
  },
  watch: {
    value(val) {
      if (this.isValid) this.$emit("change", val);
    },
    focus() {
      if (this.focus === false) {
        this.setOpen(false);
      }
    }
  },
  mounted() {
    document.addEventListener("keyup", this.nextItem);
  },
  methods: {
    // native events
    handleFocus(value) {
      this.focus = true;
      this.evaluateOpen(value);
    },
    handleBlur() {
      this.focus = false;
      // this.setOpen(false);
    },
    handleInput(value) {
      this.$emit("input", value);
      this.evaluateOpen(value);
    },
    handleChange(value) {
      // this.$nextTick(() => {
      //   console.log(`im in search and model is ${this.value}`);
      //   console.log(`im second and model is ${value}`);
      //   // this.$emit("change", value);
      // });
      // this.validate(value);
    },

    // Open / Close
    setOpen(isOpen) {
      this.isOpen = isOpen;
      if (isOpen) this.highlightIndex = -1;
    },
    evaluateOpen(value) {
      // only open for more than 2 results or when value isn't equal
      if (this.searchResults.length > 1 || value !== this.searchResults[0]) {
        this.setOpen(true);
      } else {
        this.setOpen(false);
      }
    },
    outsideClick() {
      this.isOpen = false;
      this.focus = false;
    },

    setFocus() {
      this.focus = true;
    },
    suggestionSelected(option) {
      // const status = this.validate(option);

      if (option) this.value = option;
      this.isOpen = false;

      // this.$emit("input", option);
    },

    giveError() {
      this.error = true;
      setTimeout(() => (this.error = false), 1000);
    },
    down() {
      if (this.highlightIndex < this.searchResults.length - 1) {
        this.highlightIndex += 1;
      }
    },
    up() {
      if (this.highlightIndex >= 0) this.highlightIndex -= 1;
    },
    handleEnter(value) {
      // When user uses custom search input
      if (this.highlightIndex === -1 && !this.isValid) this.giveError();
      // When user uses navigation in search options
      const result = this.searchResults[this.highlightIndex];
      if (result) this.value = result;
      this.setOpen(false);
    }
  }
};
</script>

<style lang="scss">
$padding-input: 0.25em;
$padding-wrapper: 1.25em;
$padding-label: $padding-input + $padding-wrapper;

.search {
  &__outer {
    position: relative;
    margin-bottom: 1em;
    padding-top: $padding-wrapper;

    &.light {
      .search {
        &__inner {
          &::before {
            background-color: rgba(255, 255, 255, 0.767);
          }

          // On focus
          &::after {
            background-color: #fff;
          }
        }
      }
    }
  }

  &__suggestion {
    position: absolute;
    left: $padding-input;
    top: $padding-input;
    opacity: 0.3;
    z-index: 0;
  }

  &__inner {
    position: relative;
    display: flex;

    &::before {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 2px;
      background-color: #000;
    }

    // On focus
    &::after {
      content: "";
      position: absolute;
      margin-left: auto;
      margin-right: auto;
      left: 0;
      right: 0;
      width: 0;
      bottom: 0;
      height: 2px;
      transition: all 0.25s ease;
      background-color: #000;
    }

    &.focus::after {
      width: 100%;
    }
  }

  &__input {
    border: none;
    padding: $padding-input;
    background-color: transparent;
    position: relative;
    font-size: inherit;
    text-align: inherit;
    text-transform: inherit;
    font-weight: inherit;
    color: inherit;
    width: 100%;

    &:focus {
      outline: none;
    }
    &.invalid {
      color: red;
      animation: error 0.3s;
    }
  }

  &__placeholder {
    //
  }

  // Elements
  &__counter {
    text-align: right;
    text-transform: uppercase;
    font-size: 0.9rem;
    font-weight: 700;
    margin-top: 0.5em;
    color: #000;
  }

  &__label {
    position: absolute;
    z-index: 1;
    width: 100%;
    left: 0;
    text-align: inherit;
    padding-left: $padding-input;
    top: $padding-label;
    transition: all 0.2s ease;
    pointer-events: none;

    &.dirty {
      top: 0.25em;
      // transform: scale(0.75);
      font-size: 0.75em;
    }
  }

  &__menu {
    position: absolute;
    width: 100%;
    visibility: hidden;
    z-index: 10;
    list-style: none;
    padding-left: 0;
    border: 1px solid $color-grey-1;
    box-shadow: 0 5px 15px -2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transform: translateY(5px);
    transition: all 0.3s ease-in-out;
    max-height: 16em;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
    overflow: scroll;

    &.visible {
      transform: translateY(0);
      visibility: visible;
      opacity: 1;
    }
  }

  &__option {
    padding: 0.5em 1em;
    cursor: pointer;
    background-color: $color-white;

    &:last-of-type {
      border-bottom-left-radius: 4px;
      border-bottom-right-radius: 4px;
    }

    &.highlighted {
      background-color: $color-grey-1;
      // color: $color-white;
    }
  }
}

@keyframes error {
  8%,
  41% {
    -webkit-transform: translateX(-5px);
  }
  25%,
  58% {
    -webkit-transform: translateX(5px);
  }
  75% {
    -webkit-transform: translateX(-2.5px);
  }
  92% {
    -webkit-transform: translateX(2.5px);
  }
  0%,
  100% {
    -webkit-transform: translateX(0);
  }
}
</style>
