import React from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import {Block} from '../../Block';
import {TimeNumberEditor} from './TimeNumberEditor';
import {Row} from '../../Row';
import {Col} from '../../Col';
import {TimeAmPmEditor} from './TimeAmPmEditor';

let instanceCounter = 0;

export class TimePicker extends React.PureComponent {
    static propTypes = {
        value: PropTypes.shape({
            hours: PropTypes.number,
            minutes: PropTypes.number
        }),
        onChange: PropTypes.func.isRequired, // function({minutes, hours}) {}
        is24hour: PropTypes.bool,
        onPanelFocus: PropTypes.func.isRequired,
        onBackToCalendar: PropTypes.func.isRequired,
        ariaDescription: PropTypes.string.isRequired,
        hourIncreaseBtnAriaLabel: PropTypes.string.isRequired,
        hourDecreaseBtnAriaLabel: PropTypes.string.isRequired,
        minuteIncreaseBtnAriaLabel: PropTypes.string.isRequired,
        minuteDecreaseBtnAriaLabel: PropTypes.string.isRequired,
        amAriaLabel: PropTypes.string.isRequired,
        pmAriaLabel: PropTypes.string.isRequired,
        amPmSwitcherLabel: PropTypes.string.isRequired,
        enablePMTitle: PropTypes.string.isRequired,
        enableAMTitle: PropTypes.string.isRequired
    };

    static defaultProps = {
        value: {
            hours: 0,
            minutes: 0
        },
        is24hour: true
    };

    constructor(props, ctx) {
        super(props, ctx);
        this.instanceId = ++instanceCounter;
    }

    getMaxHour = () => {
        return this.props.is24hour ? 23 : 11;
    };

    onTimeEditorChange = updates => {
        const {onChange, value} = this.props;
        onChange({...value, ...updates});
    };

    isAmMode() {
        const {value} = this.props;
        const {hours} = value;

        return hours < 12;
    }

    renderAmPMSwitcher() {
        const {
            amAriaLabel,
            pmAriaLabel,
            enableAMTitle,
            enablePMTitle,
            amPmSwitcherLabel
        } = this.props;
        const isAm = this.isAmMode();
        return (
            <TimeAmPmEditor
                isAm={isAm}
                onAmPmChange={this.handleChangeAmPm}
                amLabel={amAriaLabel}
                pmLabel={pmAriaLabel}
                amPmSwitcherLabel={amPmSwitcherLabel}
                enableAMTitle={enableAMTitle}
                enablePMTitle={enablePMTitle}
            />
        );
    }

    onHoursChanges = hours => {
        this.onTimeEditorChange({hours});
    };

    handleChangeMinutes = minutes => {
        if (minutes === -1) {
            minutes = 59;
        }

        if (minutes === 60) {
            minutes = 0;
        }

        this.onTimeEditorChange({minutes});
    };

    handleChangeAmPm = isSwitchToAM => {
        const isCurrentAmMode = this.isAmMode();
        const isModeChanged = isSwitchToAM === !isCurrentAmMode;
        const {value} = this.props;
        const oldHours = value.hours;

        let newHours = null;

        if (isModeChanged) {
            if (oldHours !== 12) {
                if (isSwitchToAM) {
                    newHours = oldHours - 12;
                } else {
                    newHours = oldHours + 12;
                }
            } else {
                newHours = 0;
            }
        }

        if (newHours !== null) {
            this.onHoursChanges(newHours);
        }
    };

    getHoursDisplayValue() {
        const {value, is24hour} = this.props;

        if (is24hour || this.isAmMode() || value.hours === 12) {
            return value.hours;
        }

        return value.hours - 12;
    }

    handleChangeHours = newHours => {
        let hours = newHours;

        if (!this.props.is24hour) {
            if (this.isAmMode()) {
                if (hours > 11) {
                    hours = 0;
                }

                if (hours < 0) {
                    hours = 11;
                }
            } else {
                hours = newHours + 12;

                if (hours === 24) {
                    hours = 12;
                }

                if (hours > 24) {
                    hours = 13;
                }
            }
        }

        this.onHoursChanges(hours);
    };

    renderTimeColon() {
        return (
            <div className="rc-datepicker-colon">
                <div className="time-text text-center">:</div>
            </div>
        );
    }

    handleStopPropagation = e => e.stopPropagation();

    handleBackToCalendar = e => this.props.onBackToCalendar();

    render() {
        const {
            value,
            onPanelFocus,
            is24hour,
            ariaDescription,
            hourIncreaseBtnAriaLabel,
            hourDecreaseBtnAriaLabel,
            minuteDecreaseBtnAriaLabel,
            minuteIncreaseBtnAriaLabel
        } = this.props;
        const descriptionId = `time-picker-description-${this.instanceId}`;

        return (
            <Block
                className="rc-datepicker-time-editor"
                addHorizontalOffset
                addTopOffset
                onKeyUp={this.handleStopPropagation}
                onFocus={onPanelFocus}
                role="group"
                aria-describedby={descriptionId}>
                <p className="sr-only" id={descriptionId}>
                    {ariaDescription}
                </p>
                <Row>
                    <Col sm={3} md={3} xs={3}>
                        <TimeNumberEditor
                            testAutomationId="hoursEditor"
                            decreaseButtonLabel={hourDecreaseBtnAriaLabel}
                            increaseButtonLabel={hourIncreaseBtnAriaLabel}
                            onShiftTabAwait={this.handleBackToCalendar}
                            value={this.getHoursDisplayValue()}
                            onChange={this.handleChangeHours}
                            max={this.getMaxHour()}
                            min={0}
                        />
                    </Col>
                    <Col sm={1} md={1} xs={1}>
                        {this.renderTimeColon()}
                    </Col>
                    <Col sm={3} md={3} xs={3}>
                        <TimeNumberEditor
                            testAutomationId="minutesEditor"
                            increaseButtonLabel={minuteIncreaseBtnAriaLabel}
                            decreaseButtonLabel={minuteDecreaseBtnAriaLabel}
                            value={value.minutes}
                            onChange={this.handleChangeMinutes}
                            valueDisplayFormat={value => _.padStart(value, 2, '0')}
                            max={11}
                            min={0}
                        />
                    </Col>
                    <Col sm={3} md={3} xs={3}>
                        {is24hour ? null : this.renderAmPMSwitcher()}
                    </Col>
                </Row>
            </Block>
        );
    }
}
