<template>
  <div class="d-flex flex-wrap align-items-end gapped">
    <div v-if="displayFilters && filtersAdded.length" class="d-flex flex-wrap">
      <div v-for="(filter, index) in filtersAdded" :key="uid + index + filter.key + '_display_filter'" class="mr-2">
        <div class="text-muted filter-label">
          {{ filter.fd.name }}
        </div>
        <div class="bg-gray rounded text-center btn">
          {{ filter.fd.type === 'date' ? formatDate(filter.fr.value) : filter.fr.value }}
          <a class="simple-anchor" href="javascript:;" @click="deleteFilter(index)">
            <span class="mdi mdi-close"></span>
          </a>
        </div>
      </div>
    </div>
    <div class="dropdown">
      <button :id="`ddMB-${uid}`" :class="`btn ${btnType} dropdown-toggle`" type="button" data-toggle="dropdown" aria-expanded="false">
        <i class="mdi mdi-filter-variant" />
        {{ $t('filter') }}
        <span v-show="filtersAdded.length" :class="`badge ${badgeType}`">{{ filtersAdded.length }}</span>
      </button>
      <div class="dropdown-menu p-3" :aria-labelledby="`ddMB-${uid}`" @click.stop>
        <draggable :list="filtersAdded" handle=".drag-icon" @start="dragging = true" @end="dragging = false" @change="emitChanges()">
          <div v-for="(filter, index) in filtersAdded" :key="uid + index + filter.key">
            <div class="d-flex gap-1 mb-1">
              <div class="filter-column-start align-self-center">
                <div v-if="! dragging">
                  <span v-show="index === 0" class="prepend">{{ $t('where') }}</span>

                  <select v-show="index === 1" v-model="filterOperation" :class="'custom-select ' + selectClass" @change="emitChanges()">
                    <option value="And">
                      {{ $t('and') }}
                    </option>
                    <option value="Or">
                      {{ $t('or') }}
                    </option>
                  </select>

                  <span v-show="index > 1" class="prepend">{{ filterOperation }}</span>
                </div>
              </div>
              <div class="filter-column">
                <select v-model="filter.key" :class="'custom-select ' + selectClass" @change="updateFilterType($event, index)">
                  <option v-for="(f, j) in list" :key="`f2-${j}`" :value="f.key">
                    {{ f.name }}
                  </option>
                </select>
              </div>
              <div class="filter-condition">
                <select v-model="filter.fr.condition" :class="'custom-select ' + selectClass" @change="emitChanges()">
                  <option v-for="(f, j) in filter.fd.conditions" :key="`f3-${j}`" :value="f">
                    {{ f }}
                  </option>
                </select>
              </div>
              <div class="filter-column">
                <div v-if="getConditionKeyFromText(filter.fr.condition) === 'ns'"
                     class="text-muted d-flex justify-content-center align-items-center" 
                     style="height: 100%;">
                  {{ $t('no value') }}
                  <input type="hidden" :value="filter.fr.value=$t('no value')" />
                </div>
                <template v-else>
                  <input v-if="filter.fd.type === filterType.text" v-model="filter.fr.value" class="form-control" type="text" @input="emitChanges()">
                  
                  <input v-else-if="filter.fd.type === filterType.number" v-model="filter.fr.value" class="form-control" type="number" @input="emitChanges()">
                  
                  <scan-input v-else-if="filter.fd.type === filterType.scan" v-model="filter.fr.value" class="mb-0" @input="emitChanges()" />

                  <select v-else-if="filter.fd.type === filterType.select" v-model="filter.fr.value" :class="'custom-select ' + selectClass" @change="emitChanges()">
                    <option v-for="(f, j) in filter.values" :key="`f4-${j}`" :value="f.searchValue || f">
                      {{ f.displayValue || f }}
                    </option>
                  </select>
                  
                  <input-date v-else-if="filter.fd.type === filterType.date" v-model="filter.fr.value" @input="emitChanges" />
                </template>
              </div>

              <a href="javascript:;" class="text-danger align-self-center ms-2" @click="deleteFilter(index)">
                <i class="mdi mdi-delete" />
              </a>

              <i class="mdi mdi-dots-vertical align-self-center drag-icon" />
            </div>
          </div>
        </draggable>

        <div v-if="savedFiltersList && savedFiltersList.length && filtersAdded.length === 0" class="saved-filter-dropdown">
          <div v-for="(filter, index) in savedFiltersList" :key="uid + index + '_display_filter'" class="saved-filter-item" @click="selectFromFiltersList(filter)">
            <div class="saved-filter-label ">
              {{ filter.name }}
              <button class="delete-btn text-danger align-self-center" @click.stop="removeSavedFilter(filter, index)">
                <i class="mdi mdi-delete" />
              </button>
            </div>
          </div>
        </div>

        <button class="btn btn-light nowrap" :class="filtersAdded.length === 0 ? 'add-filter-btn' : ''" @click="addNewFilter">
          <i class="mdi mdi-plus" />
          <span v-if="filtersAdded.length === 0">{{ $t('add-filter') }}</span>
          <span v-else>{{ $t('add-condition') }}</span>
        </button>

        <button v-if="filtersAdded.length && enableSaveFilter" class="btn btn-light nowrap ml-1 ms-1" @click="saveFilter">
          {{ $t('save-filter') }}
        </button>

        <button v-show="enableApplyFilter && filtersAdded.length" class="btn btn-secondary ml-1 ms-1 nowrap" @click="applyFilter">
          {{ $t('apply-filter') }}
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import inputDate from '../basic/Date.vue'
import draggable from 'vuedraggable';
import { filterType, getConditionKey, condition } from '../../types';
import ScanInput from '../scanner/ScanInput.vue'
import { inputScan } from '../..';

const messages = {
  en: {
    'and': 'And',
    'or': 'Or',
    'add-condition': 'Add condition',
    'add-filter': 'Add filter',
    'apply-filter': 'Apply filter',
    'add-filter': 'Add filter',
    'save-filter': 'Save filter',
    'filter': 'Filter',
    'where': 'Where',
    'no value': 'No value',
  },
  ro: {
    'and': 'Si',
    'or': 'Sau',
    'add-condition': 'Adauga conditie',
    'add-filter': 'Adauga filtru',
    'apply-filter': 'Aplica filtru',
    'add-filter': 'Adauga filtru',
    'save-filter': 'Salveaza filtru',
    'filter': 'Filtru',
    'where': 'Unde',
    'no value': 'Nu este setat',
  },
}

export default {
  components: {
    draggable,
    ScanInput,
    ScanInput,
    inputDate,
  },

  props: {
    list: {
      type: Array,
      required: true,
      default: () => [],
    },
    selectClass: {
      type: String,
      default: ''
    },
    value: {
      type: Array,
      default: () => []
    },
    displayFilters: {
      type: Boolean,
      default: false
    },
    lang: {
      type: String,
      default: 'en'
    },
    btnType: {
      type: String,
      default: 'btn-secondary',
    },
    badgeType: {
      type: String,
      default: 'rounded-pill bg-success',
    },
    updateTimeout: {
      type: Number,
      default: 500,
    },
    enableApplyFilter: {
      type: Boolean,
      default: true
    },
    enableSaveFilter: {
      type: Boolean,
      default: false
    },
    savedFiltersList: {
      type: Array,
      default: () => []
    },
  },

  data() {
    return {
      uid: Math.floor(Math.random() * 1000000),
      filtersAdded: [],
      filterType,
      dragging: false,
      filterOperation: 'And',
      emitTimeout: false,
    }
  },
  watch: {
    value(newValue) {
      this.setFiltersByValue(newValue)
    }
  },

  mounted() {
    this.setFiltersByValue(this.value)
  },

  methods: {
    getConditionKeyFromText(conditionText) {
      const conditionKey = Object.keys(condition[this.lang]).find(
        key => condition[this.lang][key] === conditionText
      );
      return conditionKey;
    },
    $t(key) {
      if (messages[this.lang] && messages[this.lang][key]) {
        return messages[this.lang][key]
      } else {
        return `$t{${key}}`
      }
    },
    deleteFilter(index) {
      this.filtersAdded.splice(index, 1)
      this.emitChanges()

      if(! this.filtersAdded.length) {
        this.applyFilter();
      }
    },
    formatDate(d) {
      return ('0' + d.getDate()).slice(-2) + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' +
             d.getFullYear();
    },
    setFiltersByValue(value) {
      this.filtersAdded = value.map((nv) => {
        const newFilter = this.createFilter(nv.key)
        newFilter.fr.value = nv.value
        newFilter.fr.precondition = nv.precondition
        newFilter.fr.condition = condition[this.lang][nv.condition]
        return newFilter
      })
    },
    createFilter(key) {
      const filterLookup = this.list.filter(f => f.key === key)
      if (filterLookup) {
        const fd = filterLookup[0]

        let values = []

        if (typeof fd.values === 'function') {
          values = fd.values(this.getSetFilters())
        }

        const fr = {
          key,
          condition: fd ? fd.conditions[0] : undefined,
          precondition: 'and',
        }

        if (values.length && values[0].hasOwnProperty('searchValue') && values[0].hasOwnProperty('displayValue')) {
          fr.value = values[0].searchValue;
          fr.displayValue = values[0].displayValue;
        } else {
          fr.value = values.length ? values[0] : undefined;
        }

        return { fd, fr, key, id: Math.floor(Math.random() * 1000000), values }
      }

      return undefined
    },

    async updateFilterType(event, index) {
      if (event) {
        const f = this.createFilter(event.target.value)
        if (f) {
          this.filtersAdded[index] = f
        }
      }

      this.emitChanges()
    },

    addNewFilter() {
      const newFilter = this.createFilter(this.list[0].key)
      if (newFilter) {
        this.$emit('input', [...this.value,{
          key: newFilter.key,
          value: newFilter.fr.value,
          precondition: newFilter.fr.precondition,
          condition: getConditionKey(newFilter.fr.condition, this.lang)
        }])
      }
    },
    
    saveFilter() {
      this.$emit('saveFilter', this.filtersAdded.map(filter => ({
        key: filter.key,
        value: filter.fr.value,
        precondition: filter.fr.precondition,
        condition: getConditionKey(filter.fr.condition, this.lang)
      })))
    },

    getSetFilters() {
      const ret = []
      this.filtersAdded.forEach(f => {
        ret.push({
          key: f.key,
          value: f.fr.value,
          condition: getConditionKey(f.fr.condition, this.lang),
          precondition: this.filterOperation.toLowerCase(),
        })
      })
      return ret
    },

    emitChanges() {
      const vm = this
      clearTimeout(vm.emitTimeout)
      vm.emitTimeout = setTimeout(() => {
        vm.$emit('input', vm.getSetFilters())
      }, this.updateTimeout)
    },

    applyFilter() {
      this.$emit('applyFilter', this.getSetFilters())
    },

    selectFromFiltersList(filter) {
      this.$emit('input', filter.fd)
    },

    removeSavedFilter(filter, index) {
      this.$emit('DeleteSavedFilterPreviolet', filter, index);
    },
  }
}
</script>

<style scoped lang="scss">
.filter-column-start {
  min-width: 100px;
}
.filter-column {
  min-width: 160px;
}
.filter-condition {
  min-width: 140px;
}
.drag-icon {
  cursor: grab;
}
.prepend {
  margin-left: 13px;
}

.mx-datepicker {
  width: 100% !important;
 }
.bg-gray {
  background-color: #ced4da;
  cursor: default !important;
  height: 38px;
  min-width: 38px;
  overflow: hidden;
}
.gapped {
  gap: 0.5rem;
}
.simple-anchor {
  color: black;
}
.filter-label {
  margin-top: -24px;
}
.nowrap {
  white-space: nowrap;
}
.ml-1 {
  margin-left: 0.25rem!important;
}

.saved-filter-dropdown {
  display: flex;
  flex-direction: column;
  width: max-content;
  padding: 0 0 0.75rem 0;
}

.saved-filter-item {
  padding: 0.25rem 0;

  &:hover {
    cursor: pointer;
    background-color: rgba($color: gray, $alpha: 0.05);
    border-radius: 0.25rem;
  }
}

.add-filter-btn {
  width: 100%;
}

.delete-btn {
  border: none;
  background: transparent;
  box-shadow: none;
  outline: none;
  padding: 2px 4px;
  cursor: pointer;
}
.saved-filter-label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%; 
  min-width: 170px;
  gap: 0.5rem; 
}
</style>
