<template>
  <v-container px-1 pt-1 pb-2>

    <v-layout row justify-space-between align-center mr-3>

      <v-flex xs6 class="d-inline-flex">
        <div text-xs-left>
          <ExportData
            v-if="items"
            :items="items"
            :headers="headers"/>
        </div>
        <SearchInput
          :search-text="searchText"
          :placeholder="placeholder"
          class="table-search-input"
          @change-search-text="onChangeSearchText"/>
      </v-flex>
      <v-flex xs6>
        <h2 class="primary--text text-xs-right">{{ title || model | camelify }}</h2>
      </v-flex>

    </v-layout>

    <v-data-table
      :headers="headers"
      :items="items"
      :total-items="totalItems"
      :loading="loading"
      :rows-per-page-items="rowsPerPageItems"
      :rows-per-page-text="isTableSmall ? '' : 'Rows per page'"
      :pagination.sync="pagination"
      class="elevation-1 mx-3">

      <template slot="items" slot-scope="props">
        <td
          v-for="header in headers"
          :key="header.text"
          class="text-xs-left table-cell py-0">
          <span
            v-if="header.model && Array.isArray(getValue(props.item, header.value))">
            <span
              v-for="(value, index) in getValue(props.item, header.value)"
              :key="index"
              class="active-link"
              @click="onClickRecord(value, header.model)"
              v-html="formatValue(value, header.format)">
              <span v-if="index < getValue(props.item, header.value).length">, </span>
            </span>
          </span>
          <span
            v-else-if="header.model && !Array.isArray(getValue(props.item, header.value))">
            <span
              class="active-link"
              @click="onClickRecord(getValue(props.item, header.value), header.model)"
              v-html="formatValue(getValue(props.item, header.value), header.format)"/>
          </span>
          <span
            v-else-if="header.value === 'status'"
            :class="classValue(props.item, header.value)"
            v-html="tableValue(props.item, header.value, header.format)"/>
          <span
            v-else
            v-html="tableValue(props.item, header.value, header.format)"/>
        </td>
      </template>

      <template slot="no-data">
        <td :colspan="headers.length" class="text-xs-left">
          {{ loading ? 'Querying records...' : (errorMessage || 'No records found.')}}
        </td>
      </template>

      <template slot="no-results">
        <td :colspan="headers.length" class="text-xs-left">
          {{ loading ? 'Querying records...' : 'No records found.'}}
        </td>
      </template>

      <template slot="pageText" slot-scope="props">
        Showing {{ props.pageStart }} - {{ props.pageStop }} of <span class="primary--text subheading mx-1">{{ totalItems | formatNumber }}</span> {{ model }}
      </template>

    </v-data-table>

  </v-container>
</template>

<script>
import ExportData from '@/components/search/ExportData.vue'
import SearchInput from '@/components/search/SearchInput.vue'
import { fetchListRecords } from '@/utils/api'
import { tableColumns } from '@/utils/constants'
import { SHOW_ALERT } from '@/store/actions/alert'
import { SHOW_PANEL } from '@/store/actions/panels'

import _ from 'lodash'

export default {
  name: 'DataTable',
  components: {
    ExportData,
    SearchInput
  },
  props: {
    model: String,
    title: String,
    emptySearchText: {
      type: Boolean,
      default: true
    },
    params: {
      type: Object,
      default: () => ({})
    }
  },
  data () {
    return {
      items: [],
      totalItems: null,
      loading: true,

      // table params
      headers: tableColumns[this.model],
      rowsPerPageItems: [3, 5, 10, 25, 50, 200, 500, 5000],
      pagination: {
        rowsPerPage: 3
      },

      // query params
      limit: null,
      offset: null,
      ordering: null,
      errorMessage: null,
      searchText: this.emptySearchText ? '' : this.$store.getters.searchText
    }
  },
  computed: {
    placeholder () {
      return this.$camelify(`Search ${this.model}`)
    },
    initialSearch () {
      return this.$store.getters.searchText
    }
  },
  watch: {
    searchText (newValue, oldValue) {
      if (!_.isEqual(newValue, oldValue)) {
        this.fetchData()
      }
    },
    initialSearch () {
      if (!this.emptySearchText) {
        this.searchText = this.initialSearch
      }
    },
    params (newParams, oldParams) {
      if (!_.isEqual(newParams, oldParams)) {
        this.fetchData()
      }
    },
    pagination: {
      handler () {
        this.updateTable()
      },
      deep: true
    }
  },
  methods: {
    onChangeSearchText (searchText) {
      this.searchText = searchText
    },

    tableValue (item, accessor, formatType) {
      let value = this.$get(item, accessor, '-', formatType)
      return this.highlightText(value)
    },

    formatValue (value, formatType) {
      return value
    },

    getValue (item, accessor) {
      return this.$get(item, accessor, '')
    },

    isTableSmall () {
      let tables = document.getElementsByClassName('v-datatable__actions')
      return tables && tables.length > 0 && tables[0].offsetWidth < 400
    },

    classValue (item, accessor) {
      let value = this.$get(item, accessor).toString().toLowerCase()
      return `status-${value}`
    },

    highlightText (text) {
      // let searchKeywords = this.searchText.split(' ')
      let searchKeywords = [(this.searchText || '').toLowerCase()]
      let shownText = text ? text.toString().slice(0, 41) : ''

      searchKeywords.forEach(keyword => {
        if (keyword && shownText.toLowerCase().includes(keyword)) {
          const keywordRegex = new RegExp(`(${keyword})`, 'gi')
          text = text.toString().replace(
            keywordRegex,
            '<span class="highlight">$1</span>'
          )
        }
      })
      return text
    },

    updateTable () {
      const { sortBy, descending, page, rowsPerPage } = this.pagination
      const ordering = sortBy ? `${descending ? '-' : ''}${sortBy}` : ''

      this.limit = rowsPerPage
      this.offset = rowsPerPage * (page - 1)
      this.ordering = ordering
      this.fetchData()
    },

    fetchData () {
      this.loading = true
      const {
        model,
        limit,
        offset,
        ordering,
        params,
        searchText
      } = this

      fetchListRecords(model, {
        ...params,
        limit,
        offset,
        search: searchText,
        ordering
      }).then(response => {
        this.items = response.results
        this.totalItems = response.count
        this.pages = Math.ceil(response.count / limit)
        this.loading = false
        this.errorMessage = response.error || ''
      }).catch(() => {
        this.$store.dispatch(SHOW_ALERT, {
          error: 'There is an error with the API request.'
        })
        this.loading = false
      })
    },

    onClickRecord (value, model) {
      this.$store.dispatch(SHOW_PANEL, {
        [model]: value
      })
    }
  }
}
</script>

<style lang="scss">
// .v-datatable {
//   tbody {
//     max-height: 350px; /* 10x table-cell heigh to show 10 rows */
//     overflow: auto;
//     display: block;
//   }
//   thead, tbody tr {
//     display:table;
//     width:100%;
//     table-layout:fixed; /* even columns width , fix width of table too */
//   }
// }
.table-cell {
  height: 35px !important;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 300px;
}
.v-datatable__progress th {
  height: 3px !important;
}
.v-menu__content:not(.v-autocomplete__content) {
  .v-list__tile {
    height: 23px;
  }
}
table.v-table thead tr {
  height: 50px;
}
.table-search-input {
  padding: 0 16px 16px 0 !important;
  .v-input {
    min-width: 150px;
    max-width: 150px
  }
}
div.v-datatable__actions {
  flex-wrap: nowrap;
  &__pagination {
    width: 100%;
    min-width: 170px;
    margin: 0 10px 0 10px;
  }
  &__select {
    white-space: normal;
    overflow: hidden;
    justify-content: flex-start;
    margin-right: 5px;
    max-width: 100px;
    .v-select {
      margin-left: 25px;
      margin-right: 0px;
      margin-top: 0px;
      margin-bottom: 0px;
    }
  }
  &__range-controls {
    width: 100%;
  }
  button {
    margin: 0px;
    margin-right: 5px;
  }
}
</style>
