import * as React from 'react';
import {CSSProperties} from 'react';
import {BasicConfig, BasicContainer, BasicContainerPropsInterface} from '../../render/core/Container/types';
import {IsArray, IsBoolean, IsString} from 'class-validator';
import {seriesTypes} from './types';
import componentLoader from '../../render/util/componentLoader';
import {Set} from 'immutable';
import {Spin} from '@native-ads/antd';

const echarts = require('echarts');

import './LineChart.css';

export class LineChartConfig extends BasicConfig {
    /**
     * 图表宽度
     * @public
     * @default 500
     */
    @IsString()
    width: string;

    /**
     * 图表高度
     * @public
     * @default 400
     */
    @IsString()
    height: string;

    /**
     * 是否展示提示框组件
     * @public
     * @default true
     */
    tooltip: boolean;

    /**
     * 图表标题
     * @public
     */
    @IsString()
    title: string;

    /**
     * 图例组件
     * @public
     * @default []
     */
    categories: string[];

    /**
     * 工具栏
     * @public
     * @default true
     */
    @IsBoolean()
    toolbox: boolean;

    /**
     * x轴数据
     * @public
     * @default [];
     */
    xAxisData: string[];

    /**
     * 是否支持缩放
     * @public
     * @default true
     */
    dataZoom: any;

    /**
     * 图标数据源
     * @public
     * @default []
     */
    @IsArray()
    series: {
        name: string;
        data: string[] | number[];
        icon?: string;
        smooth?: boolean;
        showSymbol?: boolean;
        areaStyle?: object;
        itemStyle?: object;
    }[];

    /**
     * CSS class
     */
    @IsString()
    className?: string;

    /**
     * 内联CSS属性
     */
    style?: CSSProperties;

    /**
     * 是否在加载
     */
    loading?: boolean;

    /**
     * 是否在图标上显示数值
     */
    chartLabel?: boolean;

    /**
     * 图例形状
     * @public
     */
    @IsString()
    icon?: string;

    /**
     * legend.data设置了 textStyle icon
     * @public
     * @default false
     */
    @IsBoolean()
    customLegend?: boolean;
}

export class LineChartPropsInterface extends BasicContainerPropsInterface {
    info: LineChartConfig;
}

export default class LineChart extends BasicContainer<LineChartPropsInterface, {}> {
    DOMElement: any;
    DOMID: string;
    isMount: boolean;
    chart: any;
    chartOptions: any = {
        title: {
            text: ''
        },
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'cross',
                label: {
                    backgroundColor: '#6a7985',
                    fontSize: '12px'
                }
            },
            textStyle: {
                fontSize: 12
            }
        },
        legend: {
            type: 'scroll',
            left: 'auto',
            right: 'auto',
            top: 'auto',
            bottom: 'auto',
            width: 'auto',
            height: 'auto',
            orient: 'horizontal',
            show: true,
            data: [],
            x: 'right'
        },
        toolbox: {
            show: false,
            itemSize: 15,
            itemGap: 5,
            right: 15,
            feature: {
                saveAsImage: {}
            }
        },
        grid: {
            left: '0%',
            right: '0%',
            bottom: '20%',
            containLabel: true
        },
        xAxis: {
            type: 'category',
            boundaryGap: false,
            data: ['']
        },
        yAxis: {
            type: 'value',
        },
        dataZoom: [
            {
                id: 'dataZoomX',
                type: 'slider',
                xAxisIndex: [0],
                filterMode: 'filter'
            }
        ],
        series: []
    };

    constructor(props: LineChartPropsInterface) {
        super(props);

        this.DOMID = `RCRE_lineChart_${Math.floor(Math.random() * 1000)}`;
    }

    componentDidMount() {
        setTimeout(() => {
            let info = this.getPropsInfo(this.props.info, this.props, [], true);
            if (!(info.series && info.series.length > 0)) {
                return;
            }
            this.chart = echarts.init(this.DOMElement);
            this.overRideChartOptions(info);
            this.chart.setOption(this.chartOptions);
        });
    }

    shouldComponentUpdate() {
        return true;
    }

    componentDidUpdate(prevProps: LineChartPropsInterface) {
        let info = this.getPropsInfo(this.props.info, this.props, [], true);
        if (!(info.series && info.series.length > 0)) {
            return;
        }
        if (!this.chart) {
            this.chart = echarts.init(this.DOMElement);
        }
        this.overRideChartOptions(info);
        this.chart.setOption(this.chartOptions, true);
    }

    private overRideChartOptions(info: LineChartConfig) {
        // title
        this.chartOptions.title.text = info.title;

        // tooltip
        if (info.tooltip === false) {
            delete this.chartOptions.tooltip;
        }

        if (info.categoriesUp) {
            if (Array.isArray(info.categoriesUp)) {
                this.chartOptions.xAxis = [
                    {
                        type: 'category',
                        boundaryGap: false,
                        data: info.categoriesUp

                    },
                    {
                        type: 'category',
                        boundaryGap: false,
                        data: info.categories
                    }
                ];
                Object.assign(this.chartOptions.xAxis[0], info.xAxis && info.xAxis[0]);
                Object.assign(this.chartOptions.xAxis[1], info.xAxis && info.xAxis[1]);
            }
        } else {
            if (Array.isArray(info.categories)) {
                Object.assign(this.chartOptions.xAxis, info.xAxis);
                this.chartOptions.xAxis.data = info.categories;
            }
        }

        if (info.toolbox === false) {
            delete this.chartOptions.toolbox;
        }

        if (Array.isArray(info.dataZoom)) {
            this.chartOptions.dataZoom = info.dataZoom;
        }
        if (Array.isArray(info.series)) {
            let legends = Set<string>();
            let legendsAgroup: any = [];
            this.chartOptions.series = info.series.map(item => {
                let ret: seriesTypes = {
                    name: item.name,
                    type: 'line',
                    data: item.data,
                    smooth: item.smooth || false,
                    showSymbol: item.showSymbol ,
                    areaStyle: item.areaStyle || {},
                    itemStyle: item.itemStyle || {}
                };

                if (info.chartLabel) {
                    ret.label = {
                        normal: {
                            show: true,
                            position: 'top'
                        }
                    };
                }

                if (info.customLegend) {
                    legendsAgroup.push({
                        name: item.name,
                        icon: item.icon || 'circle',
                        textStyle: info.textStyle || {}
                    });
                } else {
                    legends = legends.add(item.name);
                }
                return ret;
            });
            Object.assign(this.chartOptions.legend, info.legends);

            if (info.customLegend) {
                this.chartOptions.legend.data = legendsAgroup;
            } else {
                this.chartOptions.legend.data = legends.toArray();
            }
            Object.assign(this.chartOptions.grid, info.grid);
            Object.assign(this.chartOptions.yAxis, info.yAxis);
            Object.assign(this.chartOptions.tooltip, info.tooltip);
        }
    }

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

        const style = {
            width: info.width || '100%',
            height: info.height || 500,
            ...info.style
        };

        const noDatetyle = {
            width: info.width || '100%',
            height: info.noDateheight || 100,
            border: '1px solid #e9e9e9',
            textAlign: 'center',
            lineHeight: (info.noDateheight || 100) + 'px',
            borderRadius: '4px',
            color: '#5c6b77'
        };

        const refCallback = (ref: any) => {
            if (ref) {
                this.DOMElement = ref;
            }
        };

        let $loading;

        if (this.isUnderContainerEnv()) {
            $loading = this.getValueFromDataStore('$loading') || false;
        } else {
            $loading = info.loading;
        }
        let childrenElement = (
            <Spin spinning={$loading} wrapperClassName="rcre-spin">
                <div id={this.DOMID} ref={refCallback} className={info.className} style={style}/>
            </Spin>
        );

        let noDateElement = (
            <div style={noDatetyle}><span>暂无数据</span></div>
        );

        if ((!info.series || info.series.length === 0) && !$loading) {
            this.chart = null;
            return noDateElement;
        }
        return this.renderChildren(info, childrenElement);   
    }
}

componentLoader.addComponent('lineChart', LineChart, LineChartPropsInterface);
