import { Host, h } from "@stencil/core";
import { cls, getId, isEmpty, tinyMDtoHTML } from "../../utils/helpers";
import { Lang } from "../../services/lang";
import axios from "axios";
export class XDatatable {
    constructor() {
        /**
         * Datatable ID
         */
        this.tableId = getId('datatable');
        this.loading = undefined;
        this.sorting = undefined;
        this.message = undefined;
        this.dataset = { items: [] };
        this.activeFilters = [];
        this.showFilters = undefined;
        this.filters = [];
        this.columns = [];
        this.fetch = undefined;
        this.pagination = undefined;
        this.search = undefined;
        this.fluid = undefined;
        this.paginationLimit = 50;
        this.groupBy = undefined;
        this.groupSort = 'asc';
    }
    /**
     * Element event on slot make changes
     */
    handleSlotChange() {
        this.computeChildColumns();
        this.computeChildFilters();
        this.moveChildFilters();
    }
    /**
     * Update the child columns and render the result
     */
    computeChildColumns() {
        this.columns = Array.from(this.el.children)
            .filter(tab => tab.nodeName.toLowerCase().startsWith('x-datatable-col'))
            .map(el => el);
    }
    /**
     * Update the child filters and render the result
     */
    computeChildFilters() {
        this.filters = Array.from(this.el.children)
            .filter(tab => tab.nodeName.toLowerCase() === 'x-datatable-filter')
            .map(filter => filter);
    }
    /**
     * Move each filter to slot
     */
    moveChildFilters() {
        const container = this.el.querySelector('.filter-items');
        this.filters.filter(filter => !filter.classList.contains('ready'))
            .forEach(filter => {
            container.appendChild(filter);
            filter.classList.add('ready');
        });
    }
    /**
     * Build the request form data
     */
    buildRequestBody() {
        var _a, _b;
        const data = {};
        if (this.keyword) {
            data.search = this.keyword;
        }
        if (this.activeFilters.length > 0) {
            data.filters = Object.keys(this.activeFilters).reduce((_, field) => {
                var _a, _b, _c, _d, _e, _f, _g;
                _[(_a = this.activeFilters[field]) === null || _a === void 0 ? void 0 : _a.field] = {
                    type: (_c = (_b = this.activeFilters[field]) === null || _b === void 0 ? void 0 : _b.type) !== null && _c !== void 0 ? _c : null,
                    condition: (_e = (_d = this.activeFilters[field]) === null || _d === void 0 ? void 0 : _d.condition) !== null && _e !== void 0 ? _e : null,
                    value: (_g = (_f = this.activeFilters[field]) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : null,
                };
                return _;
            }, {});
            this.activeFilters.forEach(filter => {
                data.filters[filter.field] = {
                    type: filter.type,
                    condition: filter.condition,
                    value: filter.value,
                };
            });
        }
        if (this.pagination) {
            data.limit = this.paginationLimit;
            if ((_b = (_a = this.dataset) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.cursor) {
                data.cursor = this.dataset.pagination.cursor.toString();
            }
        }
        if (this.sorting) {
            data.sort = this.sorting;
        }
        if (this.groupBy) {
            data.group = {
                field: this.groupBy,
                dir: this.groupSort,
            };
        }
        return data;
    }
    /**
     * On element will mounted
     */
    componentWillLoad() {
        this.computeChildColumns();
        this.computeChildFilters();
        if (!this.columns.length) {
            return;
        }
    }
    /**
     * On element is mounted
     */
    componentDidLoad() {
        this.moveChildFilters();
        setTimeout(() => this.fetchData(), 0);
    }
    /**
     * On finish typing the search input
     */
    onSearchFinishTyping(e) {
        var _a, _b;
        const value = (_b = (_a = e.target) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null;
        this.keyword = isEmpty(value) ? null : value;
        this.fetchData();
    }
    /**
     * Force to rednder the datatable and config
     */
    onLoadMoreElements() {
        this.fetchData(true);
    }
    /**
     * Get the list of active filters
     */
    getActiveFilters() {
        return this.filters.filter(filter => filter.active);
    }
    /**
     * Show the filters dropdown
     */
    showFiltersDrowdown() {
        this.filters.filter(filter => !filter.active)
            .forEach(filter => {
            if (!this.showFilters)
                filter.dispatchEvent(new Event('clear'));
        });
        this.showFilters = !this.showFilters;
    }
    /**
     * Clean all the filters of the datatable
     */
    clearFilters() {
        this.filters.forEach(filter => {
            filter.active = false;
            filter.dispatchEvent(new Event('clear'));
        });
        this.activeFilters = [];
        this.showFilters = false;
        this.fetchData();
    }
    /**
     * Proccess all the filters and mark the active
     */
    applyValidFilters() {
        this.activeFilters = [];
        this.filters.filter(filter => filter.valid)
            .forEach(filter => {
            this.activeFilters.push({
                type: filter.type,
                field: filter.field,
                condition: filter.condition,
                value: filter.value,
            });
            filter.active = true;
        });
        this.activeFilters.length > 0 && (this.showFilters = false);
        this.fetchData();
    }
    /**
     * Fetch the request data on every change
     */
    fetchData(next = false) {
        var _a, _b, _c, _d;
        this.loading = true;
        this.message = null;
        if (!next && ((_b = (_a = this.dataset) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.cursor)) {
            this.dataset.pagination.cursor = null;
        }
        axios({
            method: 'POST',
            url: (_c = this.fetch) !== null && _c !== void 0 ? _c : window.location.href,
            data: this.buildRequestBody(),
            headers: {
                'X-CSRF-TOKEN': (_d = document.querySelector('meta[name="csrf-token"]')) === null || _d === void 0 ? void 0 : _d.getAttribute('content'),
            }
        }).then(({ data, status }) => {
            var _a, _b, _c, _d;
            if (data === null || data === void 0 ? void 0 : data.data) {
                const items = (_a = data === null || data === void 0 ? void 0 : data.data) !== null && _a !== void 0 ? _a : [];
                this.dataset = {
                    items: next ? this.dataset.items.concat(items) : items,
                    pagination: {
                        more: false,
                        total: 0,
                    }
                };
            }
            else {
                this.dataset = {
                    items: [],
                    pagination: {
                        more: false,
                        total: 0,
                    }
                };
            }
            if (this.pagination) {
                this.dataset.pagination.more = (_b = data === null || data === void 0 ? void 0 : data.more) !== null && _b !== void 0 ? _b : !isEmpty(data === null || data === void 0 ? void 0 : data.cursor);
                this.dataset.pagination.cursor = (_c = data === null || data === void 0 ? void 0 : data.cursor) !== null && _c !== void 0 ? _c : null;
            }
            this.dataset.pagination.total = (_d = data === null || data === void 0 ? void 0 : data.count) !== null && _d !== void 0 ? _d : 0;
            if (status != 200 && (data === null || data === void 0 ? void 0 : data.message)) {
                this.message = {
                    color: 'info',
                    icon: 'idea',
                    content: data === null || data === void 0 ? void 0 : data.message,
                };
                this.scrollToTop();
            }
            this.loading = false;
        }).catch(err => {
            var _a, _b, _c;
            this.loading = false;
            if (err === null || err === void 0 ? void 0 : err.response) {
                this.message = {
                    color: 'warning',
                    icon: 'hand',
                    content: (_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : err.message,
                };
                this.scrollToTop();
            }
            else {
                this.message = {
                    color: 'danger',
                    icon: 'danger',
                    content: err === null || err === void 0 ? void 0 : err.message,
                };
                this.scrollToTop();
            }
        });
    }
    /**
     * Scroll the windown to focus the top table
     */
    scrollToTop() {
        if (this.el.querySelector('.message')) {
            window.scrollTo({ top: 0, behavior: 'smooth' });
        }
    }
    /**
     * On click the TH element of header column
     */
    onClickColumn(e, col) {
        if (col.sortable) {
            const th = e.target;
            if (th.hasAttribute('data-sort')) {
                col.sortdir = col.sortdir == 'asc' ? 'desc' : 'asc';
                th.setAttribute('data-sort', col.sortdir);
            }
            else {
                this.el.querySelectorAll('[data-sort]').forEach(el => el.removeAttribute('data-sort'));
                th.setAttribute('data-sort', col.sortdir);
            }
            this.sorting = {
                field: col.field,
                dir: col.sortdir,
            };
            this.fetchData();
        }
    }
    /**
     * Render Toolbar element
     */
    renderToolbar() {
        return h("div", { class: "toolbar" }, (this.search || this.filters.length > 0) && h("x-input", { label: Lang.get('datatable.search'), typingtimeout: 2000, cleanable: true, typingindicate: true, loading: this.loading, onDoneTyping: (e) => this.onSearchFinishTyping(e), onClearInput: (e) => this.onSearchFinishTyping(e) }, this.getActiveFilters().length > 0 && h("x-tooltip", { content: Lang.get('datatable.clear-filters'), slot: "buttons" }, h("x-button", { type: "button", icon: "clean", onClick: () => this.clearFilters() })), this.filters.length > 0 && h("x-tooltip", { content: (this.activeFilters.length > 0 ? Lang.get('datatable.active-filters', {
                n: this.activeFilters.length
            }) : Lang.get('datatable.available-filters', {
                n: this.filters.length
            })), slot: "buttons" }, h("x-button", { type: "button", icon: "filter-alt", class: cls({
                'button-active': this.getActiveFilters().length > 0,
                'button-selected': this.showFilters,
            }), onClick: () => this.showFiltersDrowdown() }, this.getActiveFilters().length > 0 && h("span", { slot: "right" }, this.getActiveFilters().length))), this.filters.length > 0 && h("div", { class: cls('filters', { active: this.showFilters }) }, h("div", { class: "arrow" }), h("div", { class: "filter-items" }, h("slot", { name: "filters" })), h("x-button", { type: "button", icon: "filter-alt", color: "primary", onClick: () => this.applyValidFilters(), block: true, small: true }, Lang.get('datatable.apply')))), h("div", null, h("slot", { name: "actions" })));
    }
    /**
     * Render the datatable
     */
    renderTable() {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        return h("div", { class: "wrap" }, h("table", { key: this.tableId }, h("thead", null, h("tr", null, this.columns.map(col => h("th", { key: col.field, style: { width: `${col.width}px` }, "data-align": col.align, onClick: (e) => this.onClickColumn(e, col) }, h("span", { innerHTML: tinyMDtoHTML(col.label) }), col.sortable && h("div", { class: "sortable" }, h("i", { class: "icon-dropdown asc" }), h("i", { class: "icon-dropdown desc" })))))), h("tbody", null, this.loading && h("tr", { class: "loading" }, h("td", { colSpan: this.columns.length }, h("x-progress", { loading: true }))), this.message && h("tr", { class: "message" }, h("td", { colSpan: this.columns.length }, h("x-alert", { color: this.message.color, icon: this.message.icon }, this.message.content))), !((_b = (_a = this.dataset) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.length) && h("tr", { class: "empty" }, h("td", { colSpan: this.columns.length }, ((_c = this.keyword) === null || _c === void 0 ? void 0 : _c.length) > 0 || this.activeFilters.length > 0 ? h("i", { class: "icon-search" }) : h("i", { class: "icon-suspend" }), h("p", null, Lang.get(((_d = this.keyword) === null || _d === void 0 ? void 0 : _d.length) > 0 || this.activeFilters.length > 0 ? 'datatable.no-results' : 'datatable.empty')))), (_f = (_e = this.dataset) === null || _e === void 0 ? void 0 : _e.items) === null || _f === void 0 ? void 0 :
            _f.map(item => {
                var _a, _b;
                if (item && typeof item === 'object' && 'items' in item && 'value' in item) {
                    return [
                        h("tr", { class: "group" }, h("td", { colSpan: this.columns.length }, h("div", null, (_a = item.label) !== null && _a !== void 0 ? _a : item.value))),
                        ((_b = item.items) === null || _b === void 0 ? void 0 : _b.map(item => h("tr", null, this.columns.map(col => h("td", { style: { width: `${col.width}px` }, "data-align": col.align, "data-type": col.type }, h("x-datatable-cell", { col: col, row: item }))))))
                    ];
                }
                return h("tr", null, this.columns.map(col => h("td", { style: { width: `${col.width}px` }, "data-align": col.align, "data-type": col.type }, h("x-datatable-cell", { col: col, row: item }))));
            }), h("slot", null), ((_h = (_g = this.dataset) === null || _g === void 0 ? void 0 : _g.pagination) === null || _h === void 0 ? void 0 : _h.more) && h("tr", { class: "show-more", onClick: () => this.onLoadMoreElements() }, h("td", { colSpan: this.columns.length }, this.loading && h("x-progress", { loading: true }), !this.loading && h("a", { href: "javascript:;" }, Lang.get('datatable.show-more')))))));
    }
    /**
     * Render element
     */
    render() {
        var _a, _b, _c;
        return h(Host, { key: 'ad676b4470e69345ae145808883942a1f2722da2', class: cls({ fluid: this.fluid }) }, this.renderToolbar(), this.renderTable(), this.pagination && h("div", { key: '2f1f51b4bf4f38c1d0e963e07b8d412719f28315', class: "pagination", innerHTML: tinyMDtoHTML(Lang.get('datatable.pagination', {
                count: this.dataset.items.length,
                total: (_c = (_b = (_a = this.dataset) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.total) !== null && _c !== void 0 ? _c : 0
            })) }));
    }
    static get is() { return "x-datatable"; }
    static get originalStyleUrls() {
        return {
            "$": ["./style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["style.css"]
        };
    }
    static get properties() {
        return {
            "fetch": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Server Side proccesing route"
                },
                "attribute": "fetch",
                "reflect": false
            },
            "pagination": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enable pagination"
                },
                "attribute": "pagination",
                "reflect": false
            },
            "search": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enable search input"
                },
                "attribute": "search",
                "reflect": false
            },
            "fluid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element fluid style"
                },
                "attribute": "fluid",
                "reflect": false
            },
            "paginationLimit": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Limit of entries in pagination"
                },
                "attribute": "pagination-limit",
                "reflect": false,
                "defaultValue": "50"
            },
            "groupBy": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Group the results by"
                },
                "attribute": "group-by",
                "reflect": false
            },
            "groupSort": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "DatatableSortDir",
                    "resolved": "\"asc\" | \"desc\"",
                    "references": {
                        "DatatableSortDir": {
                            "location": "local",
                            "path": "/opt/atlassian/pipelines/agent/build/src/components/x-datatable/component.tsx",
                            "id": "src/components/x-datatable/component.tsx::DatatableSortDir"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Group sort direction"
                },
                "attribute": "group-sort",
                "reflect": false,
                "defaultValue": "'asc'"
            }
        };
    }
    static get states() {
        return {
            "loading": {},
            "sorting": {},
            "message": {},
            "dataset": {},
            "activeFilters": {},
            "showFilters": {},
            "filters": {},
            "columns": {}
        };
    }
    static get elementRef() { return "el"; }
    static get listeners() {
        return [{
                "name": "slotchange",
                "method": "handleSlotChange",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
