import IDUtil from '../../util/IDUtil';
import ComponentUtil from '../../util/ComponentUtil';
import ElasticsearchDataUtil from '../../util/ElasticsearchDataUtil';
import classNames from 'classnames';

import PropTypes from 'prop-types';

//this component relies on the collection statistics as input
class FieldSelector extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            sortField: 'title',
            sortOrder: 'down',
            filters: {
                keyword: '',
            }
        }
    }

    onSort(sortField){
        this.setState({
            sortField,
            sortOrder: this.state.sortField === sortField ? (this.state.sortOrder === 'up' ? 'down' : 'up') : this.state.sortOrder,
        })
    }

    // '~'' --> high ASCII, on end of sorting
    getStringDescriptionOrEmpty(v) {
        return v ? v.description || '~' : '~';
    }

    sortFields(fields) {
        // default to id first; to prevent unwanted shuffling
        fields = fields.sort((a,b)=>(a.id > b.id ? -1 : 1));

        if(this.state.sortField === 'title') {
            fields = fields.sort((a,b)=>(a.title > b.title ? -1 : 1));
        } else if(this.state.sortField === 'description' && this.props.descriptions) {
            fields = fields.sort((a,b) => {
                const s1 = this.getStringDescriptionOrEmpty(this.props.descriptions[a.id]);
                const s2 = this.getStringDescriptionOrEmpty(this.props.descriptions[b.id]);
                return s1 > s2 ? -1 : 1
            });
        } else if(this.state.sortField === 'type') {
            fields = fields.sort((a,b)=>(a.type > b.type ? -1 : 1));
        } else if(this.state.sortField === 'level') {
            fields = fields.sort((a,b)=>(a.level > b.level ? -1 : 1));
        } else if(this.state.sortField === 'completeness') {
            fields = fields.sort((a,b)=>(this.props.completeness['existCounts'][a.id] < this.props.completeness['existCounts'][b.id] ? -1 : 1));
        }

        switch(this.state.sortOrder){
            case 'desc':
                return fields.reverse();
            default:
                return fields;
        }
    }

    filterFields(fields) {
        if (this.state.filters.keyword){
            const keywords = this.state.filters.keyword.toLowerCase().split(' ');
            keywords.forEach((keyword)=>{
                fields = fields.filter((field)=>(
                    field.title.toLowerCase().includes(keyword) ||
                    (field.level && field.level.toLowerCase().includes(keyword)) ||
                    (
                        field.id in this.props.descriptions &&
                        this.props.descriptions[field.id].description &&
                        this.props.descriptions[field.id].description.toLowerCase().includes(keyword)
                    ) ||
                    (field.type && field.type.toLowerCase().includes(keyword))
                ));
            });
        }
        return fields;
    }


    onKeywordFilter(e) {
        this.setState({
            filters: Object.assign({},this.state.filters, {
                keyword: e.target.value
            })
        })
    }

    onSelect(field) {
        this.props.onSelect(field);
    }

    onClose() {
        this.props.onClose();
    }

    render() {
        const fields = this.sortFields(this.filterFields(this.props.fields));

        const sortArrow = <i className={"fas fa-sort-"+this.state.sortOrder}/>;

        let levelTableHead = null;

        if(this.props.showLevelColumn) {
            levelTableHead = (
                <th onClick={()=>{this.onSort('level')}}
                    className={classNames('level',{active:this.state.sortField === 'level'})}>
                    Level
                    {this.state.sortField === 'level' ? sortArrow : null}
                </th>
            )
        }

        return (
            <div className={IDUtil.cssClassName('field-selector')}>

                <div className="container">
                    <div className="close" onClick={this.onClose.bind(this)}>Close ❌</div>
                    <div className="row">
                        <div className="col-md-12">
                            <form>
                                <div className="input-group">
                                    <input type="text"
                                           className="form-control"
                                           placeholder="Search fields"
                                           onChange={this.onKeywordFilter.bind(this)}
                                           value={this.state.filters.keywords}
                                       />
                                    <span className="input-group-addon btn-effect"><i className="fas fa-search"/></span>
                                </div>
                            </form>
                            <table>
                                <thead>
                                <tr>
                                    <th onClick={()=>{this.onSort('title')}}
                                        className={classNames('title', { active:this.state.sortField === 'title'})}>
                                        Field
                                        {this.state.sortField === 'title' ? sortArrow : null}
                                        </th>

                                    {levelTableHead}

                                    <th onClick={()=>{this.onSort('description')}}
                                        className={classNames('description',{active:this.state.sortField === 'description'})}>
                                        Description
                                        {this.state.sortField === 'description' ? sortArrow : null}
                                        </th>

                                     <th onClick={()=>{this.onSort('type')}}
                                        className={classNames('type',{active:this.state.sortField === 'type'})}>
                                        Type
                                        {this.state.sortField === 'type' ? sortArrow : null}
                                        </th>

                                    <th onClick={()=>{this.onSort('completeness')}}
                                        className={classNames('completeness', {active:this.state.sortField === 'completeness'})}>
                                        Completeness
                                        {this.state.sortField === 'completeness' ? sortArrow : null}
                                        </th>

                                    <th className="select"/>
                                </tr>
                                </thead>
                                <tbody>

                                    {fields.map((field)=>(
                                        <tr className={classNames({current: this.props.selectedField === field.id})}>
                                            <td className="title" title={field.id}>
                                                {field.title}
                                            </td>
                                            {this.props.showLevelColumn ? <td className="level" title={field.level}>
                                                {field.level}
                                            </td> : null }
                                            <td className="description">
                                                {this.props.descriptions ?
                                                    (this.props.descriptions[field.id] !== undefined ?
                                                        <span>{this.props.descriptions[field.id].description || '-'}</span>
                                                    : '-')
                                                    : <i className="fas fa-circle-notch fa-spin"/>
                                                }
                                            </td>
                                            <td className="type">
                                                {field.type || '?'}
                                            </td>
                                            <td className="completeness">
                                                {this.props.completeness ?
                                                    (this.props.completeness['existCounts'][field.id] !== undefined ?
                                                    <div>
                                                        <span>{
                                                            ComponentUtil.calcCompleteness(
                                                                this.props.completeness['existCounts'][field.id],
                                                                this.props.completeness['total']
                                                            )
                                                        }%</span>
                                                        <br/>
                                                        <span className="total">
                                                            {this.props.completeness['existCounts'][field.id]} / {this.props.completeness['total']}
                                                        </span>
                                                    </div> : '-')
                                                    : <i className="fas fa-circle-notch fa-spin"/>
                                                }
                                            </td>
                                            <td className="select">
                                                <button className="btn btn-primary"
                                                        onClick={this.onSelect.bind(this,field)}>
                                                    Select
                                                </button>
                                            </td>
                                        </tr>
                                    ))}
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
};

FieldSelector.propTypes = {
    fields : PropTypes.array.isRequired, //list of available fields
    onClose : PropTypes.func.isRequired, //when the user closes this component from view
    onSelect : PropTypes.func.isRequired, //when the user selects a field to be analysed

    completeness : PropTypes.object, //completeness information per field
    descriptions : PropTypes.object, //list of field descriptions, helping the user to understand what each field is for
    showLevelColumn : PropTypes.bool, //whether or not to show an extra column with metadata hierarchy information
    selectedField : PropTypes.string, //ID/name of the currently selected field
};

export default FieldSelector;
