<!--
   Copyright 2018 Brigham Young University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->
<template>
<section class="content-padding">
  <h1 class="queue-title">
    {{packetListName}}
    <button class="btn btn-outline-primary" @click="refresh">
      <span class="sr-only">Refresh</span>
      <font-awesome-icon :icon="syncIcon" />
    </button>
  </h1>
  <div>
    <div>
      <ul class="pagination">
        <li class="page-item" v-if="notFirstPage">
          <a class="page-link" href="`?offset=0`" aria-label="First" @click.prevent="loadPage('first')">First</a>
        </li>
        <li class="page-item" v-if="notFirstPage">
          <a class="page-link" :href="`?offset=${prevPageOffset}`" aria-label="Previous" @click.prevent="loadPage('prev')">
            <span aria-hidden="true"><font-awesome-icon :icon="prevIcon" /></span>
            <span class="sr-only">Previous</span>
          </a>
        </li>
        <li v-for="page in pageCount" :class="{ 'page-item': true, active: isPageActive(page) }">
          <a v-if="page !== '...'"
            class="page-link"
            :href="`?offset=${(page - 1) * query.limit}`"
            @click.prevent="loadPage(page)">{{page}}</a>
          <span v-else class="page-link disabled">{{page}}</span>
        </li>
        <li class="page-item" v-if="notLastPage">
          <a class="page-link" :href="`?offset=${nextPageOffset}`" aria-label="Next" @click.prevent="loadPage('next')">
            <span aria-hidden="true"><font-awesome-icon :icon="nextIcon" /></span>
            <span class="sr-only">Next</span>
          </a>
        </li>
        <li class="page-item" v-if="notLastPage">
          <a class="page-link" :href="`?offset=${lastPageOffset}`" aria-label="Last" @click.prevent="loadPage('last')">Last</a>
        </li>
      </ul>
      <span class="match-caption">
        {{currentPage}} of {{total}}
      </span>
      <table class="table table-hover table-bordered">
        <caption>
          {{currentPage}} of {{total}}
        </caption>
        <thead class="thead-light">
          <tr>
            <slot name="columns">
            <sortable-header @click="sortByName" v-bind="$props" field="applicant_name">Name</sortable-header>
            <th>ID</th>
            <th>Type</th>
            <th>Major</th>
            <sortable-header @click="sortByAdmitPeriod" v-bind="$props" field="admit_period">Admit Period</sortable-header>
            <sortable-header @click="sortByNextAction" v-bind="$props" field="next_action">Next Action</sortable-header>
            </slot>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(row, i) of data" :key="row.application_uuid">
            <slot v-bind:row="row" v-bind:i="i">
            <td><router-link :to="`/detail/${row.application_uuid}`">{{row.applicant_name}}</router-link></td>
            <td>{{row.applicant_id}}</td>
            <td>{{row.applicant_type}}</td>
            <td>{{row.applicant_major}}</td>
            <td>{{row.admit_period}}</td>
            <td>{{row.next_action_date | dateTime}}</td>
            </slot>
          </tr>
        </tbody>
      </table>
      <ul class="pagination">
        <li class="page-item" v-if="notFirstPage">
          <a class="page-link" href="`?offset=0`" aria-label="First" @click.prevent="loadPage('first')">First</a>
        </li>
        <li class="page-item" v-if="notFirstPage">
          <a class="page-link" :href="`?offset=${prevPageOffset}`" aria-label="Previous" @click.prevent="loadPage('prev')">
            <span aria-hidden="true"><font-awesome-icon :icon="prevIcon" /></span>
            <span class="sr-only">Previous</span>
          </a>
        </li>
        <li v-for="page in pageCount" :class="{ 'page-item': true, active: isPageActive(page) }">
          <a v-if="page !== '...'"
            class="page-link"
            :href="`?offset=${(page - 1) * query.limit}`"
            @click.prevent="loadPage(page)">{{page}}</a>
          <span v-else class="page-link disabled">{{page}}</span>
        </li>
        <li class="page-item" v-if="notLastPage">
          <a class="page-link" :href="`?offset=${nextPageOffset}`" aria-label="Next" @click.prevent="loadPage('next')">
            <span aria-hidden="true"><font-awesome-icon :icon="nextIcon" /></span>
            <span class="sr-only">Next</span>
          </a>
        </li>
        <li class="page-item" v-if="notLastPage">
          <a class="page-link" :href="`?offset=${lastPageOffset}`" aria-label="Last" @click.prevent="loadPage('last')">Last</a>
        </li>
      </ul>
    </div>
  </div>
</section>
</template>
<script>
  import SortableHeader from './SortableHeader'
  import range from 'lodash.range'
  import { mapState, mapGetters, mapActions } from 'vuex'
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
  import { faAngleDoubleLeft, faAngleDoubleRight, faSync } from '@fortawesome/free-solid-svg-icons'
  import { dateTimeFormat } from './dateTimeFormat'

  const pageSlice = (curr, total) => {
    console.log(`in page Slice\ncurr=${curr}, total=${total}`)
    if (curr < 4) {
      return range(1, 6).concat(['...'])
    } else if (curr > total - 3) {
      return ['...'].concat(range(total - 4, total + 1))
    }
    return ['...'].concat(range(curr - 2, curr + 3)).concat(['...'])
  }

  export default {
    name: 'Queues',
    props: ['listType', 'offset', 'sort', 'order'],
    computed: {
      currentPage () {
        const {offset, limit} = this.query
        const firstIndex = offset
        const lastIndex = Math.min(firstIndex + limit, this.total)
        return Math.min(firstIndex + 1, lastIndex) + ' - ' + (lastIndex)
      },
      notFirstPage () {
        const {offset} = this.query
        return offset > 0
      },
      notLastPage () {
        const {offset, limit} = this.query
        const total = this.total
        return offset + limit < total
      },
      pageCount () {
        const {offset, limit} = this.query
        const total = this.total
        const pages = Math.ceil(total / limit)
        const curr = Math.ceil(offset / limit)
        return pages < 2
        ? []
        : pages > 6
        ? pageSlice(curr + 1, pages)
        : pages
      },
      searchOptions () {
        return {
          listType: this.listType,
          offset: this.offset,
          sort: this.sort,
          order: this.order
        }
      },
      ...mapState({
        data: state => state.packetList.data,
        total: state => state.packetList.total
      }),
      ...mapGetters(['packetListName', 'packetListQuery']),
      query () { return this.packetListQuery },
      syncIcon () { return faSync },
      nextIcon () { return faAngleDoubleRight },
      prevIcon () { return faAngleDoubleLeft }
    },
    components: {
      FontAwesomeIcon,
      SortableHeader
    },
    filters: {
      dateTime: dateTimeFormat
    },
    watch: {
      '$route'() {
        this.fetchAndUpdate(this.listType, this.searchOptions)
      },
      '$props'() {
        this.fetchAndUpdate(this.listType, this.searchOptions)
      }
    },
    mounted: function () {
      this.fetchAndUpdate(this.listType, this.searchOptions, false)
    },
    methods: {
      ...mapActions(['fetchPacketList']),
      nextPageOffset () {
        const {offset, limit} = this.query
        return offset + limit
      },
      prevPageOffset () {
        const {offset, limit} = this.query
        return offset - limit
      },
      lastPageOffset () {
        const {limit} = this.query
        const total = this.total
        return Math.floor(total / limit) * limit
      },
      sortBy (query, field) {
        const { sort, order } = query
        const newSort = field
        const newOrder = (sort === field && order === 'asc') ? 'desc' : 'asc'
        const routerQuery = { sort: newSort, order: newOrder, offset: 0 }
        this.$router.push({path: `/list/${this.listType}`, query: routerQuery})
        window.scrollTo(0, 0)
      },
      sortByName () { this.sortBy(this.query, 'applicant_name') },
      sortByAdmitPeriod () { this.sortBy(this.query, 'admit_period') },
      sortByNextAction () { this.sortBy(this.query, 'next_action_date') },
      fetchAndUpdate (listType, query, force = true) {
        this.fetchPacketList({...query, listType, force})
      },
      refresh () {
        this.fetchAndUpdate(this.listType, this.query)
      },
      loadPage (page) {
        const {limit, offset, sort, order} = this.query
        const total = this.total
        const newOffset = page === 'first' ? 0
        : page === 'last' ? this.lastPageOffset()
        : page === 'next' ? this.nextPageOffset()
        : page === 'prev' ? this.prevPageOffset()
        : (page - 1) * limit
        this.$router.push({ path: `/list/${this.listType}`, query: {offset: newOffset, sort, order} })
        window.scrollTo(0, 0)
      },
      isPageActive (page) {
        if (page === '...') return false

        const { limit, offset } = this.query
        const pageOffset = (page - 1) * limit
        return pageOffset === offset
      }
    }
  }
</script>
<style scoped>
  .queue-title {
    display: grid;
    grid-template-columns: auto auto 1fr;
    grid-gap: 0.5rem;
    align-items: center;
  }
  .sortable {
    cursor: pointer;
  }
  .match-caption {
    padding-left: .75rem;
    color: var(--gray, #6c757d);
  }
</style>
