<template lang="pug">
    div.oc-table-container
        table.oc-table(:class="{'oc-table-auto-width': isAutoWidth, center: displayCenter}", :style="{'min-width': width}")
            thead(v-if="isHead", ref="thead", @click="_headClickHanlder($event)",)
                tr
                    th(v-if="isCheckbox")
                        input.ocTableCbx(type="checkbox", @click="headCbxClick")
                    th(v-if="isShowNumber") NO.
                    slot(name="headTr")
            tbody(ref="tbody")
                template(v-if="items && items.length > 0")
                    template(v-for="(item, index) in pageData")
                        slot(v-if="isRenderTrInSlot", name="itemTrs", :model="item", :index="index")
                        template(v-else)
                            tr(:data-id="item.id", :data-index="index", :key="item[trKey] || (item.id || index)", @click="toggleActive(item, $event)", :class="{active: activeItem && (activeItem == item || activeItem[activeKey] == item.id), checked: selectedIds.indexOf(item.id) !== -1}")
                                td(v-if="isCheckbox", @click.stop="")
                                    input.ocTableCbx(type="checkbox", :value="item", v-model="selectedItems", :checked="selectedIds.indexOf(item.id) > -1" @click="_uncheckHeadCbx")
                                td(v-if="isShowNumber") {{_getItemNo(index)}}
                                slot(name="item", :model="item", :index="index")
                            tr.trHidden.zFadeIn(v-if="isHiddenTr", :data-id="item.id")
                                slot(name="itemPlug", :model="item", :index="index")
                    template(v-if="isRenderTrInSlot")
                        slot(name="footTr")

                tr(v-else-if="items && items.length === 0")
                    td(colspan="1000") No data
                tr(v-else)
                    td(:class="isAutoWidth? 'tl':'tc'", colspan="1000", style="padding-left: 30px;") Loading ...
        
            tfoot(v-if="isPage")
                tr
                    td.pt10(colspan="1000")
                        template(v-if="isPagByStep")
                            button.xs.mr10(type="button", @click="_setPageNo(pageNo-1)", :disabled="pageNo === 1") &lt; Prev

                            button.xs.ml10(type="button", @click="_setPageNo(pageNo+1)", :disabled="pageNo >= totalPage") Next &gt;
                        template(v-else)
                            span(v-if="!isReadOnlyPager") Go to page:
                                input.sm(placeholder="Go", type="number", min="1", max="2000", :value="pageNo", @keyup.enter="_setPageNo") 
                            
                            span.ml20(v-if="!isReadOnlyPager") Show rows:
                                input(type="number", :value="pageSize", min="1", max="2000", @keyup.enter="_setPageSize")
                            
                            span.ml20 {{pageStartNo + 1}} - {{pageEndNo}} of {{total}} 

                            span.ml10.pager-btns(v-if="!isReadOnlyPager")
                                button.xs.mr5(type="button", @click="_setPageNo(1)", :disabled="pageNo === 1") &lt; First
                                button.xs.mr10(type="button", @click="_setPageNo(pageNo-1)", :disabled="pageNo === 1")  Prev

                                button.xs.ml10(type="button", @click="_setPageNo(pageNo+1)", :disabled="pageNo >= totalPage") Next 
                                button.xs.ml5(type="button", @click="_setPageNo(totalPage)", :disabled="pageNo >= totalPage") Last &gt;
</template>
<script>
    import ocDalig from './js/dialog'
    
    export default {
        name: 'oc-table',
        props: {
            allsize: { type: Number, default: null }, //ajax table，需要设置这里的值
            ajaxHandler: { type: Function, default: null }, //分页数据改变时调用，服务器端分页时-获取页面数据的回调函数 ，客户端分页时-客户端回调
            items: Array,
            isPage: { type: Boolean, default: true}, //是否显示tfoot/分页
            isReadOnlyPager: { type: Boolean, default: false }, //只显示分页信息，不显示上一页/下一页等操作按钮
            isPagByStep: { type: Boolean, default: false }, //只显示上一页/下一页
            defaultSize: { type: Number, default: 15}, //默认的分页页码大小
            isHead: { type: Boolean, default: true }, //是否显示thead
            isCheckbox: { type: Boolean, default: false }, //是否可选中
            isShowNumber: { type: Boolean, default: false }, //是否显示序号
            isAutoWidth: { type: Boolean, default: false },
            width: { type: String, default: '' },
            isKeepOneActive: { type: Boolean, default: false }, //点击时，是否自动将此行标记为active状态
            keepSelectedCrossPage: { type: Boolean, default: false },  //翻页后是否保存前一页选中的数据
            activeKey: { type: String, default: 'id'},
            displayCenter: {type: Boolean, default: false}, //是否居中显示

            isHiddenTr: { type: Boolean, default: false },  //是否存在隐藏的行，存在隐藏行时，点击每一行，或自动添加active的状态
            isRenderTrInSlot: { type: Boolean, default: false },  //是否手动渲染tbody中的tr, 一般用在一个item需要多行tr时，与isHiddenTr同时存在
            sortTable: { type: Function, default: null },  //自定义的分页方法
            trKey: { type: String, default: ''}, // 自定义v-for渲染表格行用到的key

            renderAfterajax: {type: Boolean, default:false} //是否在分页获取数据后才渲染表格
        },
        data() {
            return {
                sort: null,
                pageNo: 1,
                pageSize: this.defaultSize || 10,
                activeItem: null,  //当前激活的item，配合isKeepOneActive使用
                selectedItems: [], // 选中的存储区，如果设置了keepSelectedCrossPage，则需要手动清空
            }
        },

        computed: {
            pageStartNo() {
                return (this.pageNo - 1) * this.pageSize;
            },
            pageEndNo() {
                let total = this.pageStartNo + this.pageSize;
                let max = this.allsize || (this.items? this.items.length : 0);
                let ret = total > max? max : total;
                !ret && (ret = this.pageSize || this.defaultSize);

                return ret;
            },
            pageData() {
                let items = this.items;
                if(this.isPage){
                    if(this.allsize) {
                        items = this.items.slice(0, this.pageSize);
                    }
                    else {
                        items = this.items.slice(this.pageStartNo, this.pageStartNo + this.pageSize);
                    }
                }
                
                this.$emit('pageDataChange', items);
                return items;
            },
            
            totalPage() {
                return this.total? Math.ceil(this.total / this.pageSize) : 0;
            },

            total() {
                return this.allsize || (this.items? this.items.length : 0);
            },

            selectedIds() {
                return this.selectedItems.map(one => one.id);
            }
        },

        watch: {
            selectedItems(newSelected) {
                this.$emit('selectedChange', newSelected);
            },
            pageNo(newPageNo){
                this.$emit('pageNoChange', newPageNo);
            }   
            // items() {
            //     console.log('items change');
            // }
        },

        mounted() {
            this.addSortIconToTable();
        },
        methods: {
            _getItemNo(index) {
                return index + 1 + ((this.pageNo || 1) - 1) * (this.pageSize || 15);
            },

            addSortIconToTable() {
                [].map.call(this.$refs.thead.querySelectorAll('th[sort]'), th => {
                    if(!th.querySelector('i')) {
                        th.innerHTML = th.innerHTML + '<i class="icon-sort-up"></i><i class="icon-sort-down"></i>';
                    }
                })
            },

            clearSelected() {
                this.selectedItems = [];
                this._uncheckHeadCbx();
            },

            _uncheckHeadCbx() {
                let thead = this.$refs.thead;
                if(!thead) {
                    return;
                }
                let headIpt = this.$refs.thead.querySelector('input');
                headIpt && (this.$refs.thead.querySelector('input').checked = false);                
            },

            _setSelectedStatu() {
                this._uncheckHeadCbx();
                if(this.isCheckbox && !this.keepSelectedCrossPage) {
                    this.selectedItems = [];
                }
            },

            _setPageNo(num) {
                if(typeof num !== 'number') {
                    num = (num.srcElement || num.target).value;
                }
                if(isNaN(num)) {
                    return;
                }
                num = parseInt(num);
                if(num < 1 || num > this.totalPage) {
                    ocDalig.tips('Invalid page no!', 1000);
                    return;
                }
                let pageNo = num;
                let pageSize = this.pageSize;
                 this._setSelectedStatu();
                if(!this.renderAfterajax){
                    this.pageNo = pageNo;
                    if(this.ajaxHandler){
                       this.ajaxHandler(this)
                    }
                }else{
                    if(this.ajaxHandler) {
                        this.ajaxHandler(this,pageNo,pageSize)
                    }
                }
            },
            _setPageSize(e) {
                var val = (e.srcElement || e.target).value;
            //_setPageSize(val) {
                if(isNaN(val)) {
                    return;
                }
                let pageNo = 1;
                let pageSize = parseInt(val);
                this._setSelectedStatu();
                if(!this.renderAfterajax){
                    this.pageNo = pageNo;
                    this.pageSize = pageSize;
                    if(this.ajaxHandler){
                       this.ajaxHandler(this)
                    }
                }else{
                    if(this.ajaxHandler) {
                        this.ajaxHandler(this,pageNo,pageSize)
                    }
                }
               
                
              
            },

            toggleActive(model, event) {
                // console.log('toggle active:', model);
                if(this.isHiddenTr) {
                    event.currentTarget.classList.toggle('active');
                }  
                else if(this.isKeepOneActive) {
                    this.activeItem = model;
                }
                
                this.$emit('trClick', model, event);
            },

            headCbxClick(e) {
                var checked = e.target.checked;

                let len = this.selectedItems.length;
                this.pageData.map(one => {
                    let index = this.selectedIds.indexOf(one.id);
                    if(checked) {
                        index === -1 && this.selectedItems.push(one);
                    }
                    else {
                        index > -1 && this.selectedItems.splice(index, 1);
                    }
                })
            },

            //根据sort 设置sort icon显示
            setSortIcon(sort) {
                if(!sort) {
                    return;
                }
                let thead = $(this.$refs.thead);
                //清除原先的标记 ---
                thead.find('th').removeAttr('sorttype');
                
                for(let key in sort) {
                    let ele = thead.find('[sort="' + key + '"]');
                    $(ele).attr('sorttype', sort[key]);
                }
            },

            reset() {
                this.pageNo = 1;
                this.clearSelected();
                this.sort = null;
                $(this.$refs.thead).find('th').removeAttr('sorttype');
            },

            //点击thead时，处理排序 ----
            _headClickHanlder(event) {
                let ele = event.target || event.srcElement;
                let nodeName = ele.nodeName;
                ele = $(ele);
                if(nodeName !== 'TH') {
                    ele = ele.parents('th:eq(0)');
                }
                if(!this.items) {
                    return;
                }
                
                let sortKey = ele.attr('sort');
                if(!sortKey) {
                    return;
                }
                if(!this.sort) {
                    this.sort = {};
                }
                
                this.sort[sortKey] = 0;
                let currentSortType = ele.attr('sorttype');
                if(currentSortType === "0") {
                    this.sort[sortKey] = 1;
                }
                else if(currentSortType === "1") {
                    delete this.sort[sortKey];
                }
                this._setSelectedStatu();
                this.setSortIcon(this.sort);
                
                if(this.allsize) {
                    if(!this.renderAfterajax){
                        this.ajaxHandler && this.ajaxHandler(this);
                    }else{
                        let pageNo = this.pageNo;
                        let pageSize = this.pageSize;
                        this.ajaxHandler && this.ajaxHandler(this,pageNo,pageSize)
                    }
                   
                }
                else {
                    (this.sortTable || this.sortTableDefault)(this.sort, this.items);
                }
            },
            
            sortTableDefault(sort, items) {
                let keys = Object.keys(sort);
                
                items.sort( (a, b) => {
                    for(let i = 0; i < keys.length; i ++) {
                        let key = keys[i];
                        let sortType = sort[key];
                        if(sortType === null) {
                            continue;
                        }

                        let valA = a[key];
                        let valB = b[key];

                        let result;
                        if(typeof valA === "number" && typeof valB === "number") {
                            result = valA - valB;
                        }
                        else {
                            result = (a[key] || '').toString().localeCompare((b[key] || '').toString());
                        }
                        if(result !== 0) {
                            if(sortType === 'desc' || sortType === "0" || sortType === 0) {
                                result *= -1;
                            }
                            return result;
                        }
                    }
                })
                
                this.$emit('sortHandler', items);
            }
        }
    }
</script>
