/**
 * Calendar component
 *
 * @author Fedorov Platon
 * @date 2021-06-25
 */

import React from 'react';
import {CalendarAntd, ConfigProvider} from './CalendarAntd';
import {CalendarProps} from './Calendar.types';
import {CalendarMode} from 'antd/lib/calendar/generateCalendar';
import {Button} from '../button/Button';
import {SIZE} from '../../constants';
import {IOption, Select, Value} from '../select/Select';
import moment from 'moment';
import 'moment/locale/ru';

import * as styles from './calendar.m.scss';
import enGb from 'antd/es/locale/en_GB';
import ruRu from 'antd/es/locale/ru_RU';

interface IHeaderRenderProp {
    value: moment.Moment;
    type: CalendarMode;
    onChange: (date: moment.Moment) => void;
    onTypeChange: (type: CalendarMode) => void;
}

interface IState {
    searchYear: number;
}

export {
    CalendarProps
};

export class Calendar extends React.PureComponent<CalendarProps, IState> {
    constructor (props: CalendarProps) {
        super(props);

        moment.locale(props.i18nLocale === 'ru' ? 'ru' : 'en-gb');
    }

    override state: IState = {
        searchYear: 0
    };

    isDateDisabled = (date: moment.Moment) => {
        if (this.props.isDisabled) {
            return true;
        }

        const isDisabled = this.props.disabledDate ? this.props.disabledDate(date) : false;
        const validRange = this.props.validRange;

        if (!isDisabled && validRange) {
            return isDisabled || date.diff(validRange[0]) <= 0 || date.diff(validRange[1]) >= 0;
        }

        return isDisabled;
    }

    getMonthOptions = (date: moment.Moment) => {
        const value = moment().locale(this.props.i18nLocale);
        const current = value.clone();
        const localeData = value.localeData();
        const months: IOption[] = [];

        for (let i = 0; i < 12; i++) {
            current.month(i);

            months.push({
                title: localeData.months(current),
                value: i.toString(),
                isDisabled: this.isDateDisabled(date.clone().month(i))
            });
        }

        return months;
    }

    onChangeSelectYear = (onChange: (date: moment.Moment) => void, value: moment.Moment) => (year: Value) => {
        if (typeof year === 'string') {
            onChange(value.clone().year(parseInt(year)));
        }
    }

    onChangeSelectMonth = (onChange: (date: moment.Moment) => void, value: moment.Moment) => (month: Value) => {
        if (typeof month === 'string') {
            onChange(value.clone().month(parseInt(month)));
        }
    }

    getYearOptions = (date: moment.Moment, year: number) => {
        const options: IOption[] = [];
        const yearFrom = Math.max((this.state.searchYear || year) - 100, 0);
        const yearTo = Math.min((this.state.searchYear || year) + 100, 9999);

        for (let i = yearFrom; i <= yearTo; i += 1) {
            options.push(
                {
                    title: i.toString(),
                    value: i.toString(),
                    isDisabled: this.isDateDisabled(date.clone().year(i))
                }
            );
        }

        return options;
    }

    handleSearch = (search: string) => {
        this.setState({searchYear: parseInt(search, 10)});
    }

    headerRender = ({value, type, onChange}: IHeaderRenderProp): React.ReactNode => {
        const month = value.month().toString();
        const year = value.year();
        const showSearch = this.props.showSearch;

        return (
            <div className={styles.headerContainer}>
                <Select
                    onChange={this.onChangeSelectYear(onChange, value)}
                    value={year.toString()}
                    options={this.getYearOptions(value, year)}
                    isDisabled={this.props.isDisabled}
                    optionsMaxHeight={270}
                    showSearch={showSearch}
                    onSearch={this.handleSearch}
                />
                {type === 'month' && (
                    <Select
                        onChange={this.onChangeSelectMonth(onChange, value)}
                        value={month}
                        options={this.getMonthOptions(value)}
                        isDisabled={this.props.isDisabled}
                        optionsMaxHeight={270}
                        showSearch={showSearch}
                    />
                )}
                {this.props.onClose && (
                    <Button
                        isMinimal={true}
                        size={SIZE.MIDDLE}
                        leftIcon={'cross'}
                        onClick={this.props.onClose}
                        isDisabled={this.props.isDisabled}
                    />
                )}
            </div>
        );
    }

    override render () {
        const {showSearch, ...props} = this.props;

        return (
            <ConfigProvider locale={this.props.i18nLocale === 'ru' ? ruRu : enGb}>
                <CalendarAntd
                    {...props}
                    headerRender={this.props.headerRender || this.headerRender}
                    disabledDate={this.isDateDisabled}
                />
            </ConfigProvider>
        );
    }
}
