import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import {Icon} from '../../Icon';
import {playMessage} from '../../functions';

export const ASC = 'ASC';
export const DESC = 'DESC';
export const KEY_ENTER = 13;
export const KEY_SPACE = 32;

export class CommonListSorter extends React.Component {
    static propTypes = {
        onChangeSorting: PropTypes.func.isRequired,
        direction: PropTypes.oneOf([null, ASC, DESC]).isRequired,
        children: PropTypes.node,
        append: PropTypes.node,
        prepend: PropTypes.node,
        property: PropTypes.string,
        displayName: PropTypes.string,
        ascendingText: PropTypes.string,
        descendingText: PropTypes.string,
        sorterTitleText: PropTypes.string,
        testAutomationId: PropTypes.string,
        isGridCellSorter: PropTypes.bool
    };

    static defaultProps = {
        children: null,
        append: null,
        prepend: null,
        property: '',
        displayName: '',
        ascendingText: 'TRANSLATE:SORT_BY_ASCENDING',
        descendingText: 'TRANSLATE:SORT_BY_DESCENDING',
        sorterTitleText: 'TRANSLATE:CLICK_TO_SORT',
        testAutomationId: null,
        isGridCellSorter: false
    };

    constructor(props, context) {
        super(props, context);
        this.onClick = this.onClick.bind(this);
    }

    onClick() {
        const {
            ascendingText = '',
            descendingText = '',
            displayName,
            property,
            children,
            onChangeSorting,
            direction
        } = this.props;
        const shouldReverse = direction === ASC;

        onChangeSorting(property, shouldReverse ? DESC : ASC);

        playMessage(
            shouldReverse
                ? descendingText.replace('{name}', displayName || children || property)
                : ascendingText.replace('{name}', displayName || children || property)
        );
    }

    sorterClassName() {
        const {direction} = this.props;

        return classnames('sortable', {
            'order-asc': direction === ASC,
            'order-desc': direction === DESC
        });
    }

    handleKeyDown = e => {
        if (e.keyCode === KEY_ENTER || e.keyCode === KEY_SPACE) {
            this.onClick();
            e.preventDefault();
        }
    };

    getAccessibilityHeaderProps() {
        return {
            role: 'button',
            onKeyDown: this.handleKeyDown,
            tabIndex: 0,
            title: this.props.sorterTitleText
        };
    }

    getAriaSortName() {
        const {direction} = this.props;

        let sortName = 'none';
        if (direction === ASC) {
            sortName = 'ascending';
        }
        if (direction === DESC) {
            sortName = 'descending';
        }
        return sortName;
    }

    renderSorterIcon() {
        const {direction} = this.props;
        let iconName;

        if (direction === ASC) {
            iconName = 'chevron-down-small';
        }

        if (direction === DESC) {
            iconName = 'chevron-up-small';
        }

        if (iconName) {
            return <Icon aria-hidden="true" name={iconName} className="sorter-icon" />;
        } else {
            return (
                <Icon
                    aria-hidden="true"
                    name="chevron-down-small"
                    className="sorter-icon list-hover-arrow"
                />
            );
        }
    }

    renderGridCellSorter() {
        let {
            children,
            append,
            prepend,
            testAutomationId,
            isGridCellSorter,
            onChangeSorting,
            direction,
            displayName,
            ascendingText,
            descendingText,
            sorterTitleText,
            ...props
        } = this.props;

        props.className = classnames(props.className, this.sorterClassName());

        return (
            <th
                onClick={this.onClick}
                role="columnheader"
                aria-sort={this.getAriaSortName()}
                data-test-automation-id={testAutomationId}
                {...props}>
                {prepend}
                <div {...this.getAccessibilityHeaderProps()}>
                    {this.renderSorterIcon()}
                    {append && <span className="column-header-append">{append}</span>}
                    <div className="text-overflow">{children}</div>
                </div>
            </th>
        );
    }

    render() {
        let {isGridCellSorter, children, append, prepend, ...props} = this.props;

        if (isGridCellSorter) {
            return this.renderGridCellSorter();
        }

        props.className = classnames(props.className, this.sorterClassName());

        return (
            <div onClick={this.onClick} {...this.getAccessibilityHeaderProps()} {...props}>
                {prepend}
                {this.renderSorterIcon()}
                {append && <span className="column-header-append">{append}</span>}
                <div>{children}</div>
            </div>
        );
    }
}
