<template>
    <div class="table-container py-1 position-relative row">
        <div class="col-12"
             v-if="debug">
            current page: {{page}}
            <br />
            page length: {{pageLength()}}
            <br />
            total rows: {{totalRowsCount}}
            <br />
            <slot name="debug"></slot>
        </div>
        <div class="col-md-9 col-sm-8"
             style="padding-bottom: 0;">
            <div class="d-flex align-items-center h-100"
                 style="overflow-x: auto;padding-bottom: 2px;padding-top: 2px;">
                <slot name="actions"></slot>
            </div>
        </div>
        <div class="col-md-3 col-sm-4"
             v-if="canSearch"
             style="padding-bottom:0;">
            <input :placeholder="$t('search')"
                   v-model="search"
                   class="form-control" />
        </div>
        <div class="col-12 pb-0 mb-0 overflow-auto"
             :style="{height: height}"
             ref="tableContainer">
            <table :class="classes">
                <thead>
                    <slot name="header"></slot>
                </thead>
                <tbody>
                    <template v-for="(row, index) in pageRows">
                        <slot v-bind:row="row"
                              v-bind:index="index"></slot>
                    </template>
                </tbody>
                <tfoot>
                    <slot name="footer"></slot>
                </tfoot>
            </table>
        </div>
        <div class="col-md-4"
             v-show="paginate"
             style="padding-bottom: 0;">
            <select class="form-control"
                    v-model="rowCount">
                <option v-for="c in pageSizes"
                        :key="c"
                        :value="c">{{c}}</option>
            </select>
        </div>
        <div class="col-md-8 pb-0"
             v-show="paginate">
            <j-pagination :total-records="totalRowsCount"
                          :per-page="pageLength()"
                          :current-page="currentPage()"
                          @pagechanged="pageChanged"
                          style="height: 100%"></j-pagination>
        </div>
        <j-loading v-model="isLoading"></j-loading>
    </div>
</template>

<script>
import loc from './j-datatable.resx';
import { i18n } from "../../localization/vue-i18n";
import { toEnglishNumbers } from "./util";
import debounce from "lodash.debounce";
export default {
    i18n: i18n(loc),
    props: {
        paginate: {
            type: Boolean,
            default: true
        },
        perPage: {
            type: Number,
            default: 10
        },
        pageSizes: {
            type: Array,
            default() {
                return [5, 10, 15, 20, 25, 40, 50];
            }
        },
        debounce: {
            type: Number,
            default: 1000
        },
        bordered: {
            type: Boolean,
            default: true,
        },
        striped: {
            type: Boolean,
            default: true,
        },
        narrow: {
            type: Boolean,
            default: true,
        },
        hoverable: {
            type: Boolean,
            default: true,
        },
        canSearch: {
            type: Boolean,
            default: true
        },
        debug: {
            type: Boolean,
            default: false
        },
        mobileCards: {
            type: Boolean,
            default: true
        },
        height: {
            type: String,
            default: null
        },
    },
    data() {
        return {
            loc: loc,
            pageRows: [],
            page: 1,
            totalRowsCount: 0,
            search: '',
            runSearch: debounce(() => this.changePage(1), this.debounce),
            defaultClassList: ['table'],
            classes: [],
            isLoading: false,
            rowCount: this.perPage
        };
    },
    mounted() {
        this.refreshClassList();
    },
    methods: {
        //public methods...........................................
        refresh() {
            this.isLoading = true;
            var args = {
                request: {
                    search: this.search,
                    page: this.currentPage(),
                    pageLength: this.pageLength(),
                },
                response: {
                    totalRows: 0,
                    rows: []
                },
                callback: this.onDataProvider
            };
            this.$emit('data-provider', args);
        },
        changePage(value) {
            this.pageChanged(value);
        },
        getRows() {
            return this.pageRows;
        },
        updateRow(row, index) {
            var original = this.pageRows[index];
            var update = Object.assign({}, original, row);
            Vue.set(this.pageRows, index, update);
        },
        addRow(row) {
            this.pageRows.push(row);
        },
        deleteRow(index) {
            this.pageRows.splice(index, 1);
        },
        //private methods...........................................
        onDataProvider(eventArgs) {
            this.isLoading = false;
            const { request, response } = eventArgs;

            this.totalRowsCount = response.totalRows;
            this.pageRows.splice(0, this.pageRows.length);
            response.rows.forEach(a => this.pageRows.push(a));
        },
        pageChanged(value) {
            if (value <= 0) {
                return;
            }
            this.$refs.tableContainer.scrollTop = 0;
            this.page = value;
            this.refresh();
        },
        pageLength() {
            return this.paginate ? this.rowCount : this.totalRowsCount;
        },
        currentPage() {
            return this.paginate ? this.page : 1;
        },
        refreshClassList() {
            this.classes = this.defaultClassList.join(' ');
            if (this.bordered) {
                this.classes += ' table-bordered';
            }
            if (this.striped) {
                this.classes += ' table-striped';
            }
            if (this.narrow) {
                this.classes += ' table-sm';
            }
            if (this.hoverable) {
                this.classes += ' table-hover';
            }
            if (this.mobileCards) {
                this.classes += ' has-mobile-cards';
            }
        },
    },
    watch: {
        paginate() {
            this.refresh();
        },
        perPage() {
            this.rowCount = this.perPage;
        },
        rowCount() {
            this.refresh();
        },
        search() {
            if (this.search !== undefined && this.search !== null) {
                var s = toEnglishNumbers(this.search);
                if (s !== this.search) {
                    this.search = s;
                    return;
                }
            }
            this.isLoading = true;
            this.runSearch();
        },
        canSearch() {
            this.search = null;
        },
        bordered() {
            this.refreshClassList();
        },
        striped() {
            this.refreshClassList();
        },
        narrow() {
            this.refreshClassList();
        },
        hoverable() {
            this.refreshClassList();
        },
        mobileCards() {
            this.refreshClassList();
        },
    }
}
</script>