import React, { Component } from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';

import '../../css/admin/manage/table.scss';

import { __eafl } from 'Shared/Translations';
import ErrorBoundary from 'Shared/ErrorBoundary';
import SelectColumns from './general/SelectColumns';
import Api from 'Shared/Api';
import Totals from './general/Totals';

const initState = {
    data: [],
    pages: null,
    filtered: [],
    countFiltered: false,
    countTotal: false,
    loading: true,
    columns: [],
    selectedColumns: false,
    selectedRows: {},
    selectedAllRows: 0,
};

export default class DataTable extends Component {
    constructor(props) {
        super(props);

        this.state = {
            ...initState,
        };

        this.initDataTable = this.initDataTable.bind(this);
        this.refreshData = this.refreshData.bind(this);
        this.fetchData = this.fetchData.bind(this);
        this.getInitialFiltered = this.getInitialFiltered.bind(this);
        this.toggleSelectRow = this.toggleSelectRow.bind(this);
        this.toggleSelectAll = this.toggleSelectAll.bind(this);
        this.getSelectedRows = this.getSelectedRows.bind(this);
        this.onColumnsChange = this.onColumnsChange.bind(this);
        this.requirementMet = this.requirementMet.bind(this);
    }

    componentDidMount() {
        this.initDataTable();
    }

    componentDidUpdate( prevProps ) {
        if ( this.props.type !== prevProps.type ) {
            this.initDataTable( true );
        }
    }

    initDataTable( forceRefresh = false ) {
        // Only init when requirement is met.
        if ( ! this.requirementMet() ) {
            return;
        }

        // Use default selectedColumns or restore from LocalStorage.
        let selectedColumns = this.props.options.selectedColumns;

        if ( false !== selectedColumns ) {
            let savedSelectedColumns = localStorage.getItem( `eafl-admin-manage-${ this.props.options.id }-columns` );

            if ( savedSelectedColumns ) {
                savedSelectedColumns = JSON.parse(savedSelectedColumns);

                if (Array.isArray(savedSelectedColumns)) {
                    selectedColumns = savedSelectedColumns;
                }
            }
        }

        this.setState({
            ...initState,
            filtered: this.getInitialFiltered(),
            columns: this.props.options.columns.getColumns( this ),
            selectedColumns: selectedColumns,
        }, () => {
            if ( forceRefresh ) {
                this.refreshData();
            }
        });
    }

    getInitialFiltered() {
        const hash = window.location.hash || '';
        const queryStart = hash.indexOf( '?' );

        if ( -1 === queryStart ) {
            return [];
        }

        const query = hash.substring( queryStart + 1 );
        if ( ! query ) {
            return [];
        }

        return query.split( '&' ).reduce((filters, part) => {
            const pieces = part.split( '=' );
            const id = decodeURIComponent( pieces[0] || '' );
            const value = decodeURIComponent( pieces[1] || '' );

            if ( id && value ) {
                filters.push({ id, value });
            }

            return filters;
        }, []);
    }

    toggleSelectRow(id) {
        let newSelected = { ...this.state.selectedRows };

        newSelected[id] = !newSelected[id];

        const nbrSelected = Object.values(newSelected).filter(value => value).length;
        let selectedAllRows = 2;

        if ( 0 === nbrSelected ) {
            selectedAllRows = 0;
        } else if ( this.state.data.length === nbrSelected ) {
            selectedAllRows = 1;
        }

        this.setState({
            selectedRows: newSelected,
            selectedAllRows,
        });
    }

    toggleSelectAll() {
        const bulkEditKey = 'categories' === this.props.options.route ? 'term_id' : 'id';
        let newSelected = {};

        if ( 0 === this.state.selectedAllRows ) {
            for ( let row of this.state.data ) {
                newSelected[ row[ bulkEditKey ] ] = true;
            }
        }

        this.setState({
            selectedRows: newSelected,
            selectedAllRows: 0 === this.state.selectedAllRows ? 1 : 0,
        });
    }

    getSelectedRows() {
        return Object.keys(this.state.selectedRows).filter(id => this.state.selectedRows[id]).map(id => parseInt(id));
    }

    refreshData() {
        if ( this.refReactTable ) {
            this.refReactTable.fireFetchData();
        }
    }

    fetchData(state, instance) {
        const currentData = state.data;

        this.setState({
            loading: true,
        }, () => {
            if ( this.requirementMet() ) {
                Api.manage.getData({
                    route: this.props.options.route,
                    type: this.props.options.id,
                    pageSize: state.pageSize,
                    page: state.page,
                    sorted: state.sorted,
                    filtered: state.filtered,
                }).then(data => {
                    if ( data ) {
                        let newState = {
                            data: data.rows,
                            pages: data.pages,
                            countFiltered: data.filtered,
                            countTotal: data.total,
                            loading: false,
                        };
        
                        const bulkEditKey = 'taxonomy' === this.props.options.route ? 'term_id' : 'id';
                        if ( JSON.stringify( data.rows.map( row => row[ bulkEditKey ] ) ) !== JSON.stringify( currentData.map( row => row[ bulkEditKey ] )  ) ) {
                            newState.selectedRows = {};
                            newState.selectedAllRows = 0;
                        }
        
                        this.setState(newState);
                    }
                });
            } 
        });
    }

    onColumnsChange(id, checked) {
        let selectedColumns = [ ...this.state.selectedColumns ];

        if (checked) {
            selectedColumns.push(id);
        } else {
            selectedColumns = selectedColumns.filter(c => c !== id);
        }

        this.setState({
            selectedColumns
        });

        localStorage.setItem( `eafl-admin-manage-${ this.props.options.id }-columns`, JSON.stringify( selectedColumns ) );
    }

    requirementMet() {
        if ( this.props.options.hasOwnProperty( 'required' ) && ( ! eafl_admin.addons.hasOwnProperty( this.props.options.required ) || true !== eafl_admin.addons[ this.props.options.required ] ) ) {
            return false;
        }

        return true;
    }

    render() {
        if ( ! this.props.options ) {
            return null;
        }

        // Check if Premium requirement is met.
        if ( ! this.requirementMet() ) {
            const bundle = this.props.options.required[0].toUpperCase() + this.props.options.required.substring(1);

            return (
                <div className="eafl-admin-manage-requirement">
                    <div>*{ __eafl( 'This feature is only available in' ) }</div>
                    <a href="https://bootstrapped.ventures/easy-affiliate-links/get-the-plugin/" target="_blank">
                        { `Easy Affiliate Links ${bundle} Bundle` }
                    </a>
                </div>
            );
        }

        // Default page size.
        let defaultPageSize = 25;

        if ( eafl_admin_manage_modal.settings.hasOwnProperty( 'default_page_size' ) ) {
            let settingsPageSize = parseInt( eafl_admin_manage_modal.settings.default_page_size );

            if ( ! isNaN( settingsPageSize ) && 0 < settingsPageSize ) {
                defaultPageSize = settingsPageSize;
            }
        }

        const { data, pages, loading } = this.state;
        const selectedColumns = this.state.columns.filter(column => 'actions' === column.id || false === this.state.selectedColumns || this.state.selectedColumns.includes(column.id));
        const filteredColumns = this.state.filtered.filter( filter => '' !== filter.value && 'all' !== filter.value ).map( filter => filter.id );

        return (
            <div className="eafl-admin-manage-page">
                {
                    false !== this.state.selectedColumns
                    || this.props.options.bulkEdit
                    || this.props.options.createButton
                    ?
                    <div className="eafl-admin-manage-header">
                        {
                            false === this.state.selectedColumns
                            ?
                            <div></div>
                            :
                            <SelectColumns
                                onColumnsChange={this.onColumnsChange}
                                columns={this.state.columns}
                                selectedColumns={this.state.selectedColumns}
                                filteredColumns={filteredColumns}
                            />
                        }
                        <div className="eafl-admin-manage-header-buttons">
                            {
                                ( false === this.state.selectedColumns || this.state.selectedColumns.includes( 'bulk_edit' ) )
                                && this.props.options.bulkEdit
                                && <button
                                    className="button button-secondary button-compact"
                                    onClick={ () => {
                                        EAFL_Modal.open( 'bulk-edit', {
                                            route: this.props.options.bulkEdit.route,
                                            type: this.props.options.bulkEdit.type,
                                            ids: this.getSelectedRows(),
                                            saveCallback: () => this.refreshData(),
                                        } );
                                    }}
                                    disabled={ 0 === this.getSelectedRows().length }
                                >{ __eafl( 'Bulk Edit' ) } { this.getSelectedRows().length } { 1 === this.getSelectedRows().length ? this.props.options.label.singular : this.props.options.label.plural }...</button>
                            }
                            {
                                this.props.options.createButton
                                ?
                                <button
                                    className="button button-primary button-compact"
                                    onClick={ () => this.props.options.createButton( this ) }
                                >{ `${__eafl( 'Create' )} ${ this.props.options.label.singular }` }</button>
                                :
                                null
                            }
                        </div>
                    </div>
                    :
                    null
                }
                <div className="eafl-admin-manage-table-container">
                    <ErrorBoundary module="Datatable">
                        <Totals
                            filtered={this.state.countFiltered}
                            total={this.state.countTotal}
                        />
                        <div className="eafl-admin-manage-table-inner">
                            <ReactTable
                                ref={(refReactTable) => {this.refReactTable = refReactTable;}}
                                manual
                                columns={selectedColumns}
                                data={ data }
                                pages={pages}
                                filtered={this.state.filtered}
                                onFilteredChange={ filtered => {
                                    this.setState( { filtered } );
                                } }
                                loading={ loading }
                                onFetchData={this.fetchData}
                                defaultPageSize={ this.props.options.hasOwnProperty( 'defaultPageSize' ) ? this.props.options.defaultPageSize : defaultPageSize }
                                pageSizeOptions={ [5, 10, 20, 25, 50, 100, 500] }
                                defaultSorted={[{
                                    id: 'id',
                                    desc: true
                                }]}
                                filterable
                                resizable={false}
                                className="eafl-admin-manage-table eafl-admin-table -highlight"
                            />
                        </div>
                    </ErrorBoundary>
                </div>
            </div>
        );
    }
}
