import {ComponentContext} from "../../utils/ComponentContext";
import {TableDescriptor} from "../../utils/tables";
import {observer} from "mobx-react";
import {action, makeObservable} from "mobx";
import {FormSelect, Pagination, Table} from "react-bootstrap";

export interface DataTableProps<T> {
    tableDescriptor: TableDescriptor<T>;
}

@observer
export class DataTable<T> extends ComponentContext<DataTableProps<T>> {
    constructor(props: DataTableProps<T>) {
        super(props);
        makeObservable(this);
    }

    header() {
        return <tr>
            {this.props.tableDescriptor.columns.map(column => <th className={'text-center'}
                                                                  key={column.key}>{column.title}</th>)}
        </tr>
    }

    body() {
        const firstColumnKey = this.props.tableDescriptor.columns[0].key;
        return this.props.tableDescriptor.data.map(row => {
            const rowAny = row as any;
            return <tr key={rowAny[firstColumnKey]}>
                {
                    this.props.tableDescriptor.columns.map(column => {
                        return <td
                            className={'text-center'}
                            key={column.key}>
                            {column.format(rowAny[column.key])}
                        </td>
                    })
                }
            </tr>
        });
    }

    isFirstPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined') {
            return true;
        }

        return this.props.tableDescriptor.page === 0;
    }

    isLastPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined' || typeof this.props.tableDescriptor.pageSize === 'undefined') {
            return true;
        }

        return this.props.tableDescriptor.page === (this.props.tableDescriptor.data.length / this.props.tableDescriptor.pageSize);
    }

    @action.bound
    goFirstPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined') {
            return;
        }

        this.props.tableDescriptor.page = 0;
    }

    @action.bound
    goLastPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined' || typeof this.props.tableDescriptor.pageSize === 'undefined') {
            return;
        }

        this.props.tableDescriptor.page = this.props.tableDescriptor.data.length / this.props.tableDescriptor.pageSize;
    }

    @action.bound
    goNextPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined' || typeof this.props.tableDescriptor.pageSize === 'undefined') {
            return;
        }

        this.props.tableDescriptor.page++;
    }

    @action.bound
    goPrevPage() {
        if (typeof this.props.tableDescriptor.page === 'undefined') {
            return;
        }

        this.props.tableDescriptor.page--;
    }

    @action.bound
    changePageSize(e: any) {
        this.props.tableDescriptor.pageSize = parseInt(e.target.value);
    }

    footer() {
        const table = this.props.tableDescriptor;
        if (typeof table.page === 'undefined' || typeof table.pageSize === 'undefined') {
            return null;
        }

        return <tr className={'text-center'}>
            <td colSpan={table.columns.length}>
                <div className={'d-flex justify-content-between'}>
                    <div/>
                    <Pagination className={'mb-0'}>
                        <Pagination.First onClick={this.goFirstPage} disabled={this.isFirstPage()}/>
                        <Pagination.Ellipsis disabled={this.isFirstPage()}/>
                        <Pagination.Prev onClick={this.goPrevPage} disabled={this.isFirstPage()}/>
                        <Pagination.Item active>{this.props.tableDescriptor.page}</Pagination.Item>
                        <Pagination.Next onClick={this.goNextPage} disabled={!this.isLastPage()}/>
                        <Pagination.Ellipsis disabled={!this.isLastPage()}/>
                        <Pagination.Last onClick={this.goLastPage} disabled={!this.isLastPage()}/>
                    </Pagination>
                    <FormSelect className={'w-auto'} onChange={this.changePageSize}>
                        <option>10</option>
                        <option>20</option>
                        <option>50</option>
                        <option>100</option>
                    </FormSelect>
                </div>
            </td>
        </tr>
    }

    render() {
        const table = this.props.tableDescriptor;
        return <Table hover striped>
            <thead>
            {this.header()}
            </thead>
            <tbody>
            {this.body()}
            </tbody>
            {
                table.pageable &&
                <tfoot>
                {this.footer()}
                </tfoot>
            }
        </Table>
    }
}