<template>
    <div class="div-tbl-docs disp-style-col sc5" style="width: 100%; height: 100%; display: inline-grid">
        <div style="width: 100%; height: 48px" class="disp-style-col">
            <div class="disp-style-row" style="margin-top: 10px">
                <p>
                    Show 
                    <select v-model="cmbEntries" @change="changeLimit()">
                        <option value="10">10</option>
                        <option value="25">25</option>
                        <option value="50">50</option>
                        <option value="100">100</option>
                    </select>
                    Entries
                </p>
                <label v-if="SRCHFIELDS" style="margin-left: auto">Search:&nbsp;<input v-model="txt_search" type="search" @change="searchWatcher()"></label>
            </div>
        </div>
        <div style="width: 100%; overflow: hidden; max-height: 100%;)">
            <div style="width: 100%; overflow: scroll; height: fit-content; max-height: 100%;">
                <table :class="(typeof tableStyle === 'undefined' ? 'table table-frozen-th table-hover table-fa-icon' : tableStyle) + ' tbl-paginate'">
                    <thead>
                    <tr>
                        <th v-if="addNumbering" style="width: 50px">#</th>
                        <th v-for="data in COLHEADERS" :key="data.id" :style="data.style" @click="reorderGroup(data.id - 1)">
                            {{ data.header }}
                        </th>
                        <th v-if="ACTIONS.data"></th>
                    </tr>
                    </thead>
                    <tbody :class="ACTIONS.data ? 'tbl-action' : ''">
                        <tr v-for="(data, index) in orderedData" :key="data.id" style="cursor: pointer">
                            <td v-if="addNumbering" style="text-align: center; vertical-align: middle">{{ index += (index === 0 ? 1 : 1) }}</td>
                            <td v-for="rowdata in DISPCOLS" :key="rowdata">
                                <div v-if="getKey(ROWPROPS, 'colname', rowdata, 'type') === null">
                                    <div>{{ data[rowdata] }}</div>
                                </div>
                                <div v-else-if="getKey(ROWPROPS, 'colname', rowdata, 'type') === 'REG' || getKey(ROWPROPS, 'colname', rowdata, 'type') === null">
                                    <div v-if="ROWPROPS.length > 0" @click="getKey(ROWPROPS, 'colname', rowdata, 'click', data)"  
                                        :style="checkFunc(ROWPROPS, 'colname', rowdata, 'style', data)">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                    <div v-else :style="typeof ROWPROPS.find(x => x.colname === rowdata).style !== 'undefined' ? ROWPROPS.find(x => x.colname === rowdata).click(data) : () => { }">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                </div>
                                <div v-else-if="getKey(ROWPROPS, 'colname', rowdata, 'type') === 'PIC'">
                                    <div v-if="ROWPROPS.length > 0" @click="getKey(ROWPROPS, 'colname', rowdata, 'click', data)"  
                                        :style="checkFunc(ROWPROPS, 'colname', rowdata, 'style', data)">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                    <div v-else :style="typeof ROWPROPS.find(x => x.colname === rowdata).style !== 'undefined' ? ROWPROPS.find(x => x.colname === rowdata).click(data) : () => { }">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                </div>
                                <div v-else-if="getKey(ROWPROPS, 'colname', rowdata, 'type') === 'DOC'">
                                    <div v-if="ROWPROPS.length > 0" @click="getKey(ROWPROPS, 'colname', rowdata, 'click', data)"  
                                        :style="checkFunc(ROWPROPS, 'colname', rowdata, 'style', data)">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                    <div v-else :style="typeof ROWPROPS.find(x => x.colname === rowdata).style !== 'undefined' ? ROWPROPS.find(x => x.colname === rowdata).click(data) : () => { }">{{ getKey(ROWPROPS, 'colname', rowdata, 'custVal') === null ? data[rowdata] : ROWPROPS.find(x => x.colname === rowdata).custVal(data, rowdata) }}</div>
                                </div>
                            </td>
                            <td>
                                <div v-if="ACTIONS.data" :class="(typeof ACTIONS.class === 'undefined' ? 'grid-container ' : '') + ACTIONS.class" :style="(typeof ACTIONS.class === 'undefined' ? 'grid-template-columns: auto auto; ' : '') + 'place-content: center'">
                                    <span :style="typeof ACTIONS.class === 'undefined' ? '' : (ACTIONS.class.includes('row') ? 'margin: 0px 2px' : 'margin: 2px 0px')" v-for="action in ACTIONS.data" :key="action.id" @click="action.click(data)" :class="action.class">{{action.title}}<i :class="action.FAicon"></i></span>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="disp-style-row" style="margin-top: 10px">
                <label>Showing {{ (this.totalitems > 0 ? this.floor + 1 : 0) }} to {{ this.totaldisp }} out of {{ this.totalitems }} entries</label>
                <div style="disp-style-row; margin-left: auto" class="div-pages">
                    <button class="git-btn" @click="movePage(false, true)">Prev</button>
                    <select @change="movePage(false, false, $event.target.value)">
                        <option v-for="index in this.page" :key="index" :id="'btn_page' + index" :selected="index === currpage">{{index}}</option>
                    </select>
                    <button class="git-btn" @click="movePage(true)">Next</button>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Paginator",
        props: {
            dataValue: [],
            tableStyle: '',
            rowItemProp: [],
            dispCols: [],
            srchFields: [],
            colHeaders:[],
            actions: [],
            addNumbering: false
        },
        data(){
            return {
                index: 1,
                count: 1,
                orderASC: true,
                floor: 0, //FOR PAGE ALGORITHM
                ceil: 10, //FOR PAGE ALGORITHM
                limit: 10, //FOR PAGE ALGORITHM
                totalitems: 0, //FOR PAGE ALGORITHM
                totaldisp: 10, //FOR PAGE ALGORITHM
                currpage: 1, //FOR PAGE ALGORITHM
                page: 0, //FOR PAGE ALGORITHM
                sortCol: 0, //FOR SORTING ALGORITHM
                cmbEntries: 10, //FOR SEARCHING ALGORITHM
                txt_search: "", //FOR SEARCHING ALGORITHM
                SRCHFIELDS: this.srchFields, //FOR SEARCHING ALGORITHM
                COLHEADERS: this.colHeaders,
                DISPCOLS: this.dispCols,
                ROWPROPS: this.rowItemProp,
                ACTIONS: this.actions,
                tblData: []
            }
        },
        computed: {
            orderedData: function () { //FOR SORTING
                try {
                    var tmpData = this.tblData.filter((d) => {
                        if (this.txt_search !== '') {
                            var match = false;
                            for (var x = 0; x < this.SRCHFIELDS.length; x++)
                                if (d[this.SRCHFIELDS[x]] !== null && d[this.SRCHFIELDS[x]] !== '' && d[this.SRCHFIELDS[x]] !== undefined)
                                    if (match = d[this.SRCHFIELDS[x]].toString().toLowerCase().includes(this.txt_search.toLowerCase().trim()))
                                        return match;
                        }
                        else return true;
                    });

                    this.limit = parseInt(this.cmbEntries);
                    this.totalitems = tmpData.length;
                    this.totaldisp = (this.ceil > this.totalitems ? this.totalitems : this.ceil);

                    tmpData = this.ceil ? tmpData.slice(this.floor, this.ceil) : tmpData;
                    
                    var sortKey = this.DISPCOLS[this.sortCol];
                    const sorting = tmpData => tmpData[sortKey].toLowerCase();

                    return _.orderBy(tmpData, sorting, (this.orderASC ? 'asc' : 'desc'));
                }
                catch {
                    var tmpData = this.tblData;
                    this.limit = parseInt(this.cmbEntries);
                    this.totalitems = tmpData.length;
                    this.totaldisp = (this.ceil > this.totalitems ? this.totalitems : this.ceil);

                    tmpData = this.ceil ? tmpData.slice(this.floor, this.ceil) : tmpData;
                    
                    var sortKey = this.DISPCOLS[this.sortCol];
                    const sorting = tmpData => { try { tmpData[sortKey].toLowerCase(); } catch { return sortKey; } };

                    return _.orderBy(tmpData, sorting, (this.orderASC ? 'asc' : 'desc'));
                }
            }
        },
        watch: {
            dataValue: {
                handler: function (val, oldVal) {
                    this.tblData = val;
                    this.totalitems = val.length;
                    this.page = Math.ceil(this.totalitems / this.limit);
                    this.ceil = this.limit;
                    this.floor = 0;
                    this.currpage = 1;
                },
                deep: true
            },
            rowItemProp: {
                handler: function (val, oldVal) {
                    this.ROWPROPS = val;
                },
                deep: true
            },
            dispCols: {
                handler: function (val, oldVal) {
                    this.DISPCOLS = val;
                },
                deep: true
            },
            srchFields: {
                handler: function (val, oldVal) {
                    this.SRCHFIELDS = val; //FOR SEARCHING ALGORITHM
                },
                deep: true
            },
            colHeaders: {
                handler: function (val, oldVal) {
                    var tmp = val;
                    tmp.forEach((item, i = -1) => {
                        item.id = i + 1;
                    });
                    this.COLHEADERS = tmp;
                },
                deep: true
            },
            actions: {
                handler: function (val, oldVal) {
                    var tmp = val;
                    tmp.forEach((item, i = -1) => {
                        item.id = i + 1;
                    });
                    this.ACTIONS = tmp;
                },
                deep: true
            }
        },
        created() {
        },
        methods: {
            checkFunc(obj, searchKey, key, objkey, funcData) {
                var output = null;
                
                try {
                    output = obj.find(x => x[searchKey] === key)[objkey];
                } catch { }

                if (typeof output === 'function')
                    return output(funcData, objkey);
                else
                    return output;
            },
            getKey(obj, searchKey, key, objkey, data = null) {
                var output = null;
                
                if (data === null) {
                    try {
                        output = obj.find(x => x[searchKey] === key)[objkey];
                    } catch { }
                }
                else {
                    try {
                        output = obj.find(x => x[searchKey] === key)[objkey](data);
                    } catch { }
                }

                return output;
            },
            searchWatcher() {
                this.limit = parseInt(this.cmbEntries);
                this.ceil = this.limit;
                this.currpage = 1;
                this.floor = 0;
                this.page = Math.ceil(this.totalitems / this.limit);
            },
            changeLimit() { //ENTRIES ALGORITHM
                this.limit = parseInt(this.cmbEntries);
                this.ceil = this.limit;
                this.floor = 0;
                this.currpage = 1;
                this.totaldisp = (this.ceil > this.totalitems ? this.totalitems : this.ceil);
                this.page = Math.ceil(this.totalitems / this.limit);
            },
            movePage(next = false, prev = false, to = -1) { //MOVE PAGE ALGORITHM
                this.limit = parseInt(this.cmbEntries);
                if (next && this.ceil < this.totalitems) {
                    this.floor += this.limit;
                    this.ceil += this.limit;
                    this.currpage++;
                }
                else if (prev && this.floor > 0) {
                    this.floor -= this.limit;
                    this.ceil -= this.limit;
                    this.currpage--;
                }
                else if (to > 0) {
                    this.floor = (to * this.limit) - this.limit;
                    this.ceil = (to * this.limit);
                    this.currpage = to;
                }
            },
            reorderGroup(sortCol = 0) {
                if (this.sortCol != sortCol)
                    this.orderASC = true;
                else
                    this.orderASC = !this.orderASC;
                this.sortCol = sortCol;
            }
        }
    }
</script>
<style scoped>
    .tbl-paginate td {
        padding: 2px 4px;
    }

    .tbl-action tr td:last-child {
        width: 1%;
        white-space: nowrap;
    }
    
    .grid-container {
        display: grid;
        width: fit-content
    }
    
    .grid-container span {
        margin: 2px;
    }
</style>