<template>
  <div
    class="simple-list ui-textbox has-label has-floating-label form-element"
    :class="focus ? 'is-active' : ''"
  >
    <div class="ui-textbox__content">
      <label
        class="ui-textbox__label"
        @click.prevent
      >
        <div
          class="ui-textbox__label-text"
          :class="labelClasses"
        >{{ label }}</div>
        <div class="simple-list-items ui-textbox__input">
          <transition-group
            name="list-items"
            tag="div"
            class="simple-list-items-wrapper"
          >
            <simple-list-item
              v-for="(item, index) in mappedKeywords"
              :key="`simple-list-${index}`"
              :index="index"
              :data="item"
              @remove="removeKeyword"
            />
          </transition-group>
          <ui-autocomplete
            v-model="text"
            :disabled="mappedKeywords.length === maxKeywordsCount"
            :suggestions="autocomplete"
            @blur="focus = false"
            @focus="focus = true"
            @input="onInputChange"
            @select="addKeyword"
          />
        </div>
        <span
          v-if="mappedKeywords.length === maxKeywordsCount"
          class="ui-textbox__feedback"
        >Reached maximum number of keywords: {{ maxKeywordsCount }}</span>
      </label>
    </div>
  </div>
</template>
<script>

import _debounce from 'lodash/debounce';
import { getKeywords } from 'Api';
import { MAX_KEYWORDS_COUNT } from 'Config';
import { DEBOUNCE_TIME } from 'Config/constants';

const {
    'simple-list-item': SimpleListItem
  } = window.kiln.inputs,
  { UiAutocomplete } = window.kiln.utils.components,
  NOT_LETTERS_SPACES_NUMBERS_RE = /[^a-zA-Z0-9 ]/gi;

export default {
  components: {
    'simple-list-item': SimpleListItem,
    UiAutocomplete
  },
  props: {
    items: {
      type: Array,
      default: () => []
    },
    label: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      isActive: false,
      autocomplete: [],
      text: '',
      focus: false
    };
  },
  computed: {
    lowerCaseText() {
      return this.text.toLowerCase();
    },
    isLabelInline() {
      return !this.mappedKeywords.length && !this.isActive && !this.text && !this.focus;
    },
    labelClasses() {
      return {
        'is-inline': this.isLabelInline,
        'is-floating': !this.isLabelInline
      };
    },
    mappedKeywords() {
      return this.items.map(text => ({ text }));
    },
    maxKeywordsCount() {
      return MAX_KEYWORDS_COUNT;
    }
  },
  watch: {
    text(val) {
      this.text = val.replace(NOT_LETTERS_SPACES_NUMBERS_RE, '');
      this.updateAutocompleteList();
    }
  },
  methods: {
    /**
     * Updates list of suggestions for autocomplete
     */
    // eslint-disable-next-line func-names
    updateAutocompleteList: _debounce(function () {
      if (this.text.length >= 3) {
        return getKeywords(this.lowerCaseText)
          .then((data) => {
            const textIndex = data.findIndex(keyword => keyword === this.lowerCaseText);

            if (textIndex >= 0) data.splice(textIndex, 1);

            this.autocomplete = [...new Set([this.lowerCaseText, ...data])];
          })
          .catch(console.error);
      }
    }, DEBOUNCE_TIME),
    /**
     * Adds keyword to metaKeywords array
     */
    addKeyword() {
      if (this.items.length < MAX_KEYWORDS_COUNT) {
        this.$emit('saveKeywords', this.items.concat(this.lowerCaseText));
        this.text = '';
        this.autocomplete = [];
      }
    },
    /**
     * Remove keyword from keyword list
     * @param {number} index Index of keyword item to be removed
     */
    removeKeyword(index) {
      this.$emit('saveKeywords', [...this.items.slice(0, index), ...this.items.slice(index + 1)]);
    },
    /**
     * Handle on focus event
     * @param {item} item Item to be added
     */
    onFocus() {
      this.isActive = true;
    },
    /**
     * Handle on blur event
     * @param {item} item Item to be added
     */
    onBlur() {
      this.isActive = false;
    },
    /**
     * Handle string when in the input changes
     */
    onInputChange() {
      this.text = this.text.replace(NOT_LETTERS_SPACES_NUMBERS_RE, '');

      if (this.text) {
        const firstItem = this.autocomplete[0] || '';

        if (this.lowerCaseText === firstItem.slice(0, firstItem.length - 1)) {
          this.autocomplete.shift();
        }

        this.autocomplete.unshift(this.lowerCaseText);
        this.autocomplete = [...new Set(this.autocomplete)]; // ensure no duplicates
      } else {
        this.autocomplete = [];
      }
    }
  }
};
</script>
<style lang="scss" scoped>
  @import 'Styles/fonts.scss';

  .ui-autocomplete {
    flex-grow: 1;
    margin-bottom: 0;

    &.is-active:not(.is-disabled) /deep/ .ui-autocomplete__input,
    &.is-disabled /deep/ .ui-autocomplete__input,
    /deep/ .ui-autocomplete__input {
      border-bottom-width: 0;
      font-size: $standard-font-size;
    }
  }

  .simple-list {
    width: 100%;

    .simple-list-items {
      align-items: center;
      display: flex;
      flex-flow: row wrap;
      height: auto;
      justify-content: flex-start;
    }

    .simple-list-items-wrapper {
      align-items: flex-start;
      display: inline-flex;
      flex: 0 0 auto;
      flex-flow: row wrap;
      justify-content: flex-start;
      max-width: 100%;
    }

    .list-items-enter,
    .list-items-leave-to {
      opacity: 0;
    }

    .list-items-enter-to,
    .list-items-leave {
      opacity: 1;
    }

    .list-items-enter-active,
    .list-items-leave-active {
      transition: opacity 250ms cubic-bezier(.4, 0, .2, 1);
    }
  }
</style>
