import * as React from 'react';
import {BasicContainer, BasicContainerPropsInterface} from '../../render/core/Container/types';
import {DatePicker} from '@native-ads/antd';
import {DatePickerCommonConfig} from '../DatePicker/DatePicker';
import * as moment from 'moment';
import componentLoader from '../../render/util/componentLoader';

import 'rc-calendar/assets/index.css';
import 'rc-time-picker/assets/index.css';
import { compileExpressionString } from '../../render/util/vm';
import StartOf = moment.unitOfTime.StartOf;

const LowLevelRangePicker = require('rc-calendar/lib/RangeCalendar');
const zhCN = require('rc-calendar/lib/locale/zh_CN');
const RangePicker = DatePicker.RangePicker;

export class RangePickerConfig extends DatePickerCommonConfig {
    /**
     * 默认日期
     */
    defaultValue: [string, string];

    /**
     * 不使用Input，而是直接渲染时间选择器
     */
    pure: boolean;

    /**
     * 写入到数据模型的日期格式
     */
    format?: string;

    /**
     * 自定义数据绑定
     */
    value: [string, string];

    /**
     * 没有输入的提示文字
     */
    placeholder: [string, string];

    /**
     * 开始时间
     */
    startTime?: string;

    /**
     * 结束时间
     */
    endTime?: string;

    /**
     * 提供可快捷选择的配置
     */
    rangeSelectConfig?: {
        /**
         * 以什么时间单位开始
         */
        'startOf': StartOf,
        /**
         * 开始时间偏移天数
         */
        'startOfOffset': number,
        /**
         * 以什么时间单位结束
         */
        'endOf': StartOf,
        /**
         * 结束时间偏移天数
         */
        'endOfOffset': number,
        /**
         * 按钮标题
         */
        'title': string
    }[];
}

export class RangePickerPropsInterface extends BasicContainerPropsInterface {
    info: RangePickerConfig;
}

export class AbstractRangePicker extends BasicContainer<RangePickerPropsInterface, {}> {
    constructor(props: RangePickerPropsInterface) {
        super(props);

        this.handleChange = this.handleChange.bind(this);
        this.disabledDate = this.disabledDate.bind(this);
    }

    componentWillMount() {
        let info = this.props.info;

        if (this.props.$setData && info.name && info.defaultValue) {
            let defaultValue = info.defaultValue;
            defaultValue = compileExpressionString(defaultValue, this.getRuntimeContext());
            this.props.$setData(info.name, defaultValue);
        }
    }

    private handleChange(dates: [moment.Moment, moment.Moment], dateStrings: string[]) {
        if (this.props.$setData && this.props.info) {
            const info = this.getPropsInfo(this.props.info);
            this.props.$setData(info.name, dateStrings);

            this.commonEventHandler('onChange', {
                value: dateStrings
            });
        }
    }

    private disabledDate(info: RangePickerConfig) {
        return (startValue: moment.Moment) => {
            let startTime = info.startTime;
            let endTime = info.endTime;
            let flag = false;

            if (!startValue) {
                startValue = moment().startOf('day');
            }

            if (startTime) {
                flag = startValue.valueOf() < moment(startTime).valueOf();
            }

            if (endTime && !flag) {
                flag = startValue.valueOf() > moment(endTime).valueOf();
            }

            return flag;
        };
    }

    render() {
        let info = this.getPropsInfo(this.props.info, this.props, ['nameES']);

        if (!info.name && !info.value) {
            return this.errorReport('name or value property is required for RangePicker component', 'div');
        }

        if (!this.isUnderContainerEnv()) {
            return this.errorReport('RangePicker component should be under container component control', 'div');
        }

        let value = this.getValueFromDataStore(info.name);

        if (value && !(value instanceof Array)) {
            return this.errorReport('invalid value for rangePicker component', 'div');
        }

        let rangePickerValue: any = [];

        if (value) {
            rangePickerValue = [moment(value[0]), moment(value[1])];
        }

        const format = info.format || 'YYYY-MM-DD';

        if (info.pure) {
            return (
                <LowLevelRangePicker
                    showToday={false}
                    showWeekNumber={false}
                    dateInputPlaceholder={['开始时间', '结束时间']}
                    locale={zhCN}
                    showOk={false}
                    showClear={false}
                    selectedValue={rangePickerValue}
                    format={format}
                    disabledDate={this.disabledDate(info)}
                    onChange={(time: [moment.Moment, moment.Moment]) => {
                        if (time.length === 2) {
                            this.commonEventHandler('onComplete', {
                                startTime: time[0].format(info.format),
                                endTime: time[1].format(info.format)
                            }, true);
                        }

                        this.handleChange(time, time.map(ti => ti.format(format)));
                    }}
                />
            );
        }

        let rangeSelect = {};
        if (info.rangeSelectConfig) {
            info.rangeSelectConfig.map((item) => {
                rangeSelect[item.title] = [
                    moment().startOf(item.startOf).subtract(item.startOfOffset, 'days'),
                    moment().endOf(item.endOf).add(item.endOfOffset, 'days')];
            });
        }
        return (
            <RangePicker
                value={rangePickerValue}
                onChange={this.handleChange}
                disabledDate={this.disabledDate(info)}
                allowClear={false}
                ranges={rangeSelect}
            />
        );
    }
}

componentLoader.addComponent('rangePicker', AbstractRangePicker, RangePickerPropsInterface);
