<template>
    <table class="table table-striped table-dark">
        <thead>
        <tr>
            <th>
            </th>
            <th scope="col" v-for="(column, index) in columns" :key="index">
                <div class="input-group">
                    <div class="input-group-prepend">
                        <button
                            :class="[ 'btn', column === sortBy ? 'btn-outline-info' : 'btn-outline-secondary' ]"
                            @click="toggleSort(column)"
                        >
                            {{ column }}
                            <span :class="{ 'text-info': column === sortBy }">
                                    <font-awesome-icon :icon="getSortIcon(column)"/>
                                </span>
                        </button>
                    </div>
                    <input
                        type="text"
                        class="form-control"
                        placeholder="filter"
                        :value="filters[column]"
                        @input="changeFilter(column, $event.target.value)"
                    >
                </div>
            </th>
            <th>
                <slot name="header_actions"/>
            </th>
        </tr>
        </thead>
        <tbody v-for="(item, index) in internalItems" :key="item[keyName]" style="border-top: none">
        <tr @click="toggle(index)">
            <td>
                <font-awesome-icon icon="angle-right" style="width: 1em;" v-if="collapsed[index]"/>
                <font-awesome-icon icon="angle-down" style="width: 1em;" v-else/>
            </td>
            <td v-for="(column, index) in columns" :key="index">{{ item[column] }}</td>
            <td>
                <slot v-bind:id="index" v-bind:item="item" name="actions"/>
            </td>
        </tr>
        <tr v-if="!collapsed[index]">
            <td :colspan="columns.length + 2">
                <slot v-bind:id="index" v-bind:item="item" name="detail"/>
            </td>
        </tr>
        </tbody>
    </table>
</template>

<script>
import DataContainer from '@/mixins/data-container';
import router from '../router';
import {mapGetters} from "vuex";

export default {
    name: 'ExpandableTable',
    mixins: [DataContainer],
    created() {
        this.columns.map(e => ({
            k: e,
            v: this.$store.getters.getFilters[e]
        })).filter(e => e.v).forEach(e => this.setFilter(e.k, e.v));

        const query = this.route ? (this.route.query ? this.route.query.collapsed : null) : null;
        if (query !== null && query !== undefined) {
            this.collapsed = this.unpackInt(parseInt(query), this.internalItems.length);
        } else {
            this.collapsed = this.internalItems.map(() => true);
        }
    },
    data() {
        return {
            collapsed: [],
        };
    },
    computed: {
        ...mapGetters(['route']),
    },
    methods: {
        changeFilter(col, val) {
            this.setFilter(col, val);
            let newquery = Object.entries({
                ...this.$store.getters.getFilters,
                [col]: val
            }).reduce((a, [k, v]) => (v ? {...a, [k]: v} : a), {});
            router.push({query: newquery});
        },
        packInt(arr) {
            return arr.reduce((a, e, i) => a + (e ? 0 : 2 ** i), 0);
        },
        unpackInt(n, l) {
            return [...Array(l)].map((e, i) => (n & 2 ** i) === 0);
        },
        toggle(index) {
            const collapsed = [...this.collapsed]
            collapsed[index] = !collapsed[index];
            this.collapsed = collapsed;
        },
    },
    watch: {
        collapsed: {
            handler() {
                const encoded = this.packInt(this.collapsed).toString()
                if (this.route.query.collapsed !== encoded)
                    this.$router.push({
                        ...this.route,
                        query: {...this.route.query, collapsed: encoded}
                    });
            },
            deep: true,
        },
    },
};
</script>

<style>
.table-body-move {
    transition: transform 1s;
}
</style>