/* eslint-disable @typescript-eslint/no-empty-interface */
import {ConfiguredComponent} from '@befe/brick-core'
import dayjs, {Dayjs} from 'dayjs'
import {createDelayActionQueue, safeInvoke} from '@befe/brick-utils'
import {UiPanel} from '../../ui-comps/ui-panel'
import {UiPanelTitle} from '../../ui-comps/ui-panel-title'
import {UiItemLayout} from '../../ui-comps/ui-item-layout'
import {getMonthRows} from '../../utils/date-utils'
import {UILayoutItem} from '../../ui-comps/ui-item'
import {TypeLayoutItem} from '../../module-defs/ui-types'
import {localeDictDatePicker} from '../../locale'
import {createAside} from './create-generic-aside'

export interface MultiMonthPanelProps {
    value: number[]
    displayedDate: Dayjs
    hideNow?: boolean
    getDisabledItem?: (date: Dayjs, firstDayOfCurrentUnit: Dayjs) => boolean
    onDisplayedDateChange: (date: Dayjs) => void
    onPrevYear: () => void
    onNextYear: () => void
    onToggleZooming?: () => void
    onClick: (value?: number) => void
}

/**
 */
export class MultiMonthPanel extends ConfiguredComponent<MultiMonthPanelProps> {
    componentLocale = localeDictDatePicker
    actionQueue = createDelayActionQueue()
    aside = createAside({
        getDisplayed: () => this.props.displayedDate,
        onDisplayedChange: (displayedDate: Dayjs) => this.props.onDisplayedDateChange(displayedDate),
        handleUiUpdated: (syncScrolling) => this.actionQueue.pushAction(syncScrolling),
    })

    componentDidMount() {
        this.aside.syncAsideScroll()
        this.actionQueue.execute()
    }

    componentDidUpdate() {
        this.actionQueue.execute()
    }

    render() {
        return (
            <UiPanel
                titleElem={this.renderPanelTitle()}
                contentElem={this.renderPanelContent()}
                asideElem={this.renderPanelAside()}
                contentType={'month'}
            />
        )
    }

    private renderPanelTitle() {
        const yearTitle = this.getLocaleText(
            'get_year_title',
            // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
            this.props.displayedDate as any
        )

        return (
            <UiPanelTitle
                text={yearTitle}
                isZooming
                withZoomingIcon={Boolean(this.props.onToggleZooming)}
                rangeControl={'none'}
                rangeShowType={'both'}
                onFastLeftClick={this.handlePrevYear}
                onFastRightClick={this.handleNextYear}
                onZoomingClick={this.props.onToggleZooming}
            />
        )
    }

    private readonly handlePrevYear = () => {
        this.props.onPrevYear()
        this.aside.syncAsideScroll()
    }

    private readonly handleNextYear = () => {
        this.props.onNextYear()
        this.aside.syncAsideScroll()
    }

    private readonly getMonthText = (month: number) => {
        return this.getLocaleText('get_month_text', month)
    }

    private renderPanelContent() {
        const date = this.props.displayedDate
        const year = date.year()

        const thisMonth = dayjs().startOf('month')
        const boundRenderItem = this.renderItem.bind(this, {
            todayValue: thisMonth.valueOf(),
            today: thisMonth,
        })

        return (
            <UiItemLayout
                rows={getMonthRows(this.getMonthText, year)}
                // eslint-disable-next-line react/jsx-no-bind
                renderItem={boundRenderItem}
            />
        )
    }

    private renderItem(
        {
            todayValue,
            today,
        }: {
            todayValue: number
            today: Dayjs
        },
        item: TypeLayoutItem
    ) {
        const itemData = item.data!
        const itemValue = itemData.date.valueOf()
        const selected = this.props.value.includes(itemValue)
        const isDisabled = safeInvoke(
            this.props.getDisabledItem,
            itemData.date,
            today
        )

        return {
            elem: <UILayoutItem
                key={item.key}
                value={itemValue}
                selected={selected}
                disabled={isDisabled}
                text={item.text}
                outside={itemData.outside}
                today={!this.props.hideNow && itemValue === todayValue}
                onClick={this.props.onClick}
            />,
        }
    }

    private renderPanelAside() {
        return this.aside.render()
    }

}
