'use strict';
import React from 'react';
import PropTypes from 'prop-types';
import {FormControl} from './FormControl';
import _ from 'lodash';
import {BSDatePicker} from './BSDatePicker';
import moment from 'moment';
import {getConfig} from '../../../utils';
import classnames from 'classnames';
import {Icon} from '../Icon';

export class DatePickerControl extends FormControl {
    static propTypes = {
        ...FormControl.propTypes,
        handsEditable: PropTypes.bool,
        hasOnlyDate: PropTypes.bool,
        hasOnlyTime: PropTypes.bool,
        isValidDate: PropTypes.func,
        hasStringFormat: PropTypes.bool,
        hasTimestampFormat: PropTypes.bool,
        hasMomentFormat: PropTypes.bool,
        hasDateFormat: PropTypes.bool,
        viewMode: PropTypes.string,
        locale: PropTypes.string,
        testAutomationId: PropTypes.string,
        disabled: PropTypes.bool,
        closeOnTab: PropTypes.bool,
        timeFormat: PropTypes.string,
        dateFormat: PropTypes.string,
        setPrevMonthText: PropTypes.string,
        setNextMonthText: PropTypes.string,
        setPrevYearText: PropTypes.string,
        setNextYearText: PropTypes.string,
        setPrevDecadeText: PropTypes.string,
        setNextDecadeText: PropTypes.string,
        changeMonthText: PropTypes.string,
        changeYearText: PropTypes.string,
        setNextHourText: PropTypes.string,
        setPrevHourText: PropTypes.string,
        setNextMinuteText: PropTypes.string,
        setPrevMinuteText: PropTypes.string,
        changePMAMText: PropTypes.string
    };

    static defaultProps = {
        ...FormControl.defaultProps,
        handsEditable: false,
        hasOnlyDate: false,
        hasOnlyTime: false,
        isValidDate: null,
        hasStringFormat: false,
        hasTimestampFormat: false,
        hasMomentFormat: false,
        hasDateFormat: true,
        viewMode: 'days',
        locale: 'en_US',
        testAutomationId: 'controlDatePicker',
        disabled: false,
        closeOnTab: false,
        setPrevMonthText: 'TRANSLATE:SET_PREV_MONTH',
        setNextMonthText: 'TRANSLATE:SET_NEXT_MONTH',
        setPrevYearText: 'TRANSLATE:SET_PREV_YEAR',
        setNextYearText: 'TRANSLATE:SET_NEXT_YEAR',
        setPrevDecadeText: 'TRANSLATE:SET_PREV_DECADE',
        setNextDecadeText: 'TRANSLATE:SET_NEXT_DECADE',
        changeMonthText: 'TRANSLATE:CHANGE_MONTH',
        changeYearText: 'TRANSLATE:CHANGE_YEAR',
        setPrevHourText: 'TRANSLATE:SET_PREV_HOUR',
        setNextHourText: 'TRANSLATE:SET_NEXT_HOUR',
        setPrevMinuteText: 'TRANSLATE:SET_PREV_MINUTE',
        setNextMinuteText: 'TRANSLATE:SET_NEXT_MINUTE',
        toggleAMPMText: 'TRANSLATE:TOGGLE_AM_PM',
        dateFormat: null
    };

    renderDay(props, currentDate) {
        let day = currentDate.date();
        let selected = props.className.indexOf('rdtActive') !== -1;
        let active =
            !this.props.disabled &&
            (props.className.indexOf('rdtOld') === -1 &&
                props.className.indexOf('rdtNew') === -1 &&
                props.className.indexOf('rdtDisabled') === -1);
        return (
            <td
                role={active ? 'button' : 'presentation'}
                tabIndex={active ? 0 : undefined}
                aria-label={active ? day : undefined}
                aria-selected={selected ? 'true' : undefined}
                {...props}
                data-test-automation-id={`day${day}`}>
                {day}
            </td>
        );
    }

    renderMonth(props, monthIndex) {
        let locale = getLocale(this.props);
        let month = moment()
            .locale(locale)
            .month(monthIndex);
        let formattedMonth = _.capitalize(month.format('MMM').substring(0, 3)); // month name, 3 first letters in upper case
        let label = month.format('MMMM');
        let selected = props.className.indexOf('rdtActive') !== -1;
        let active = !this.props.disabled;
        return (
            <td
                role={active ? 'button' : 'presentation'}
                tabIndex={active ? 0 : undefined}
                aria-label={label}
                aria-selected={selected ? 'true' : undefined}
                {...props}
                data-test-automation-id={`month${monthIndex + 1}`}>
                {formattedMonth}
            </td>
        );
    }

    renderYear(props, year) {
        let selected = props.className.indexOf('rdtActive') !== -1;
        let active = !this.props.disabled;
        return (
            <td
                role={active ? 'button' : 'presentation'}
                tabIndex={active ? 0 : undefined}
                aria-label={year}
                aria-selected={selected ? 'true' : undefined}
                {...props}
                data-test-automation-id={`year${year}`}>
                {year}
            </td>
        );
    }

    render() {
        let self = this;
        let props = this.getPropsFromContext();
        let hasOnlyDate = false;
        let hasOnlyTime = false;
        let disabled = props.disabled;
        let inputProps = {disabled, ...props.inputProps};
        let timeFormat = props.timeFormat || true;
        let dateFormat = props.dateFormat;
        if (props.hasOnlyDate) {
            hasOnlyDate = !!props.hasOnlyDate;
        } else if (props.hasOnlyTime) {
            hasOnlyTime = !!props.hasOnlyTime;
        }
        if (!props.handsEditable) {
            inputProps = {
                ...inputProps,
                readOnly: true
            };
        }

        const {testAutomationId, closeOnTab} = props;

        return (
            <div
                data-test-automation-id={testAutomationId}
                className={classnames('rc-datepicker', {'rc-datepicker-disabled': disabled})}>
                <Icon name="calendar" aria-hidden="true" />
                <BSDatePicker
                    {...props}
                    componentClass="datePicker"
                    locale={getLocale(props)}
                    value={getValue(props)}
                    ref="control"
                    closeOnTab={closeOnTab}
                    closeOnSelect
                    inputProps={inputProps}
                    timeFormat={!hasOnlyDate && timeFormat}
                    dateFormat={dateFormat ? dateFormat : !hasOnlyTime}
                    onChange={value => {
                        if (_.isFunction(props.onChange)) {
                            props.onChange(getFormatted(props, value));
                        }
                    }}
                    renderDay={this.renderDay.bind(this)}
                    renderMonth={this.renderMonth.bind(this)}
                    renderYear={this.renderYear.bind(this)}
                    isValidDate={(currentDate, selectedDate) => {
                        if (_.isFunction(props.isValidDate)) {
                            return props.isValidDate(
                                getViewMode(props, self.refs.control),
                                getFormatted(props, currentDate),
                                getFormatted(props, selectedDate)
                            );
                        }
                        return true;
                    }}
                />
            </div>
        );
    }
}

function getValue(props) {
    const value = props.value;
    if (!value) {
        return null;
    }
    if (typeof value === 'number') {
        return new Date(props.value);
    }
    if (typeof value === 'string' && moment(value).isValid()) {
        return moment(value).toDate();
    }
    if (value instanceof Date) {
        return value;
    }
    return value.toDate();
}

function getLocale(props) {
    return props.locale || getConfig().userLanguage || 'en_US';
}

function getFormatted(props, value) {
    const hasStringFormat = props.hasStringFormat;
    const hasTimestampFormat = props.hasStringFormat;
    const hasMomentFormat = props.hasMomentFormat;
    if (!value) {
        return null;
    }
    if (typeof value === 'string') {
        return value;
    }
    if (hasStringFormat) {
        return value.format();
    }
    if (hasTimestampFormat) {
        return Number(value.toDate());
    }
    if (hasMomentFormat) {
        return value;
    }
    return value.toDate();
}

function getViewMode(props, control) {
    if (control) {
        // todo: this lucid hardcode otherwise not working
        // todo: this temporary implementation and in the future this component should be re-implemented w/o hardcode
        return control.state.currentView || 'days';
    }
    return props.viewMode || 'days';
}
