/**
 * 将请求返回的图表展示数据解析为前台展示用的config
 */
import moment from 'moment';
import EllipsisTooltip from '../components/common/ellipsisTooltip/index';
import { deepAssign, numberFormat } from '../utils/baseUtils';
import STATISTICS_OPTION from '../components/chartDesigner/sections/statisticsOption.json';
import themes from '../components/chartDesigner/sections/style/theme/index';
import EChartsMedia from './EChartsMedia';

export default function(viewType, data, chartConfig, themeName, styleConfig, drillDown) {
    if(!data) {
        return {};
    }
    try {
        let t = themes.find(t => t.name === themeName);
        let theme = t ? t.config : themes[0].config;
        let o, themeConfig;
        switch(viewType) {
            case 'bar': {
                themeConfig = deepAssign({}, theme.base, theme.bar, theme.xAxis, theme.yAxis, theme.dataZoom);
                o = barOption(data, chartConfig, themeConfig, styleConfig, drillDown);
                break;
            }
            case 'pie': {
                themeConfig = deepAssign({}, theme.base, theme.pie);
                o = pieOption(data, chartConfig, themeConfig, styleConfig, drillDown);
                break;
            }
            case 'line': {
                themeConfig = deepAssign({}, theme.base, theme.line, theme.xAxis, theme.yAxis, theme.dataZoom);
                o = lineOption(data, chartConfig, themeConfig, styleConfig, drillDown);
                break;
            }
            case 'scatter': {
                themeConfig = deepAssign({}, theme.base, theme.scatter, theme.xAxis, theme.yAxis, theme.dataZoom);
                o = scatterOption(data, chartConfig, themeConfig, styleConfig);
                break;
            }
            case 'aggregateTable': {
                themeConfig = deepAssign({}, theme.base, theme.aggregateTable);
                o = aggregateTableOption(data, chartConfig, themeConfig, styleConfig);
                break;
            }case 'dataView' : {
                themeConfig = deepAssign({}, theme.base, theme.dataView);
                o = dataViewOption(data, chartConfig, themeConfig, styleConfig);
                break;
            }
            case 'indicator':
                themeConfig = deepAssign({}, theme.base, theme.indicator);
                o = indicatorOption(data, chartConfig, themeConfig, styleConfig);
                break;
            default:{
                o = {};
                break;
            }
        }
        return o;
    }catch(e) {
        console.error(e);
    }
}

function barOption(data, barConfig, themeConfig, styleConfig, drillDown) {
    if(!data) {
        return {
            drillDown
        };
    }
    const { xAxis, yAxis, groupBy } = barConfig;
    const { barMaxWidth, barMinHeight, barGap, stack, labelVisible, labelPosition, labelDistance,
        labelRotate, xNameLocation, xNameGap, xNameRotate, xLabelHiddenCover, xLabelRotate, dataZoomVisible,
        xLabelMargin, yNameLocation, yNameGap, yNameRotate, labelZeroVisible } = styleConfig;
    let xTitle = xAxis?`${xAxis.column.label}`:null
    let yTitle = yAxis?`${yAxis.column.label}`:null
    let xGranularityV = xAxis?`${xAxis.granularity.value}`:null
    let hasGroupBy = !!groupBy && !!groupBy.key;
    let legendVisible = hasGroupBy;
    data.serieses = data.serieses || [];

    //钻取逻辑
    if(drillDown){
        let curDrillDown = drillDown.slice(-1)[0];
        xTitle = xAxis?`${curDrillDown.label}`:null;
        if(curDrillDown.type==='time'){
            xGranularityV = curDrillDown.showDataType
        }else {
            xGranularityV = null;
        }
    }

    let option = deepAssign({
        originConfig: {
            ...barConfig
        },
        tooltip : {
            trigger: "axis",
            axisPointer: {
                type: "cross"
            }
        },
        legend: {
            show: legendVisible
        },
        xAxis: [{
            type: 'category',
            nameLocation: (xNameLocation === '' || xNameLocation === null || xNameLocation === undefined) ? 'end' : xNameLocation,
            nameGap: (xNameGap === '' || xNameGap === null || xNameGap === undefined) ? 15 : Number(xNameGap),
            nameRotate: (xNameRotate === '' || xNameRotate === null || xNameRotate === undefined) ? 0 : Number(xNameRotate),
            axisLabel: {
                interval: xLabelHiddenCover === undefined ? 'auto' : (!!xLabelHiddenCover ? 'auto' : 0),
                rotate: (xLabelRotate === '' || xLabelRotate === null || xLabelRotate === undefined) ? 0 : Number(xLabelRotate),
                margin: (xLabelMargin === '' || xLabelMargin === null || xLabelMargin === undefined) ? 8 : Number(xLabelMargin),
            },
            data: data.xAxis.map(d => {
                let gv= xGranularityV;
                if( !d ) {
                    return '空';
                }
                let xv = d;
                if(gv === 'halfYear') {
                    let arr = d.split('-H');
                    xv = `${arr[0] || '-'} ${['上半年', '下半年'][arr[1] - 1]}`;
                }else if(gv === 'month') {
                    let arr = d.split('-');
                    xv = `${arr[0] || '-'}/${arr[1]}`;
                }else if(gv === 'quarter') {
                    let arr = d.split('-');
                    xv = `${arr[0] || '-'} ${['一', '二', '三', '四'][arr[1] - 1] + '季度'}`;
                }else if(gv === 'week') {
                    let arr = d.split('-');
                    xv = (arr[0] || '-') + ' ' + arr[1] + '周'
                }
                return xv;
            }),
            name: xTitle || '横轴',
        }],
        yAxis: [{
            name: yTitle || '纵轴',
            type: 'value',
            nameLocation: (yNameLocation === '' || yNameLocation === null || yNameLocation === undefined) ? 'end' : yNameLocation,
            nameGap: (yNameGap === '' || yNameGap === null || yNameGap === undefined) ? 15 : Number(yNameGap),
            nameRotate: (yNameRotate === '' || yNameRotate === null || yNameRotate === undefined) ? 0 : Number(yNameRotate),
        }],
        series: data.serieses.map(s => {
            return {
                name: !!groupBy && !!groupBy.key ? s.name : yAxis.column.label,
                type: 'bar',
                data: s.value.map(v => numberFormat(v)),
                barMaxWidth: barMaxWidth || 60,
                barMinHeight: barMinHeight || 0,
                barGap: barGap || '30%',
                stack: !!groupBy && !!groupBy.key && !!stack,
                label: {
                    normal: {
                        show: !!labelVisible,
                        position: labelPosition || 'inside',
                        distance: (labelDistance === '' || labelDistance === null || labelDistance === undefined) ? 5 : Number(labelDistance),
                        rotate: (labelRotate === '' || labelRotate === null || labelRotate === undefined) ? 0 : Number(labelRotate),
                        formatter: !labelZeroVisible ? (params) => {
                            const { value } = params;
                            return Number(value) === 0 ? '' : value;
                        } : '{c}'
                    }
                }
            }
        }),
        dataZoom: {
            show: !!dataZoomVisible
        }
    }, themeConfig);

    let mediaOption = {
        drillDown: drillDown,
        baseOption: option,
        media: EChartsMedia('bar', legendVisible, dataZoomVisible, {
            legend: option.legend
        })
    }
    
    return mediaOption;
}

function lineOption(data, lineConfig, themeConfig, styleConfig, drillDown) {
    if(!data) {
        return {
            drillDown
        };
    }
    const { labelSymbol, xNameLocation, xNameGap, xNameRotate, xLabelRotate, xLabelMargin, xLabelHiddenCover,
        yNameLocation, yNameGap, yNameRotate, stack, labelVisible, labelPosition, labelDistance, labelRotate,
        lineSmooth, labelSymbolSize, dataZoomVisible } = styleConfig;
    const { xAxis, yAxis, groupBy } = lineConfig;
    let xTitle = xAxis?`${xAxis.column.label}`:null
    let yTitle = yAxis?`${yAxis.column.label}`:null
    let hasGroupBy = !!groupBy && !!groupBy.key;
    let legendVisible = hasGroupBy;
    let xGranularityV = xAxis.granularity.value;
    data.serieses = data.serieses || [];

    //钻取逻辑
    if(drillDown){
        let curDrillDown = drillDown.slice(-1)[0];
        xTitle = xAxis?`${curDrillDown.label}`:null
        if(curDrillDown.type==='time'){
            xGranularityV = curDrillDown.showDataType
        }else {
            xGranularityV = null;
        }
    }

    let option = deepAssign({
        originConfig: {
            ...lineConfig
        },
        tooltip : {
            trigger: "axis",
            axisPointer: {
                type: "cross"
            }
        },
        legend: {
            show: legendVisible
        },
        xAxis: [{
            name: xTitle || '横轴',
            type: 'category',
            nameLocation: (xNameLocation === '' || xNameLocation === null || xNameLocation === undefined) ? 'end' : xNameLocation,
            nameGap: (xNameGap === '' || xNameGap === null || xNameGap === undefined) ? 15 : Number(xNameGap),
            nameRotate: (xNameRotate === '' || xNameRotate === null || xNameRotate === undefined) ? 0 : Number(xNameRotate),
            axisLabel: {
                interval: xLabelHiddenCover === undefined ? 'auto' : (!!xLabelHiddenCover ? 'auto' : 0),
                rotate: (xLabelRotate === '' || xLabelRotate === null || xLabelRotate === undefined) ? 0 : Number(xLabelRotate),
                margin: (xLabelMargin === '' || xLabelMargin === null || xLabelMargin === undefined) ? 8 : Number(xLabelMargin),
            },
            data: data.xAxis.map(d => {
                let gv= xGranularityV;
                if(!d) {
                    return '空';
                }
                let xv = d;
                if(gv === 'halfYear') {
                    let arr = d.split('-H');
                    xv = `${arr[0] || '-'} ${['上半年', '下半年'][arr[1] - 1]}`;
                }else if(gv === 'month') {
                    let arr = d.split('-');
                    xv = `${arr[0] || '-'}/${arr[1]}`;
                }else if(gv === 'quarter') {
                    let arr = d.split('-');
                    xv = `${arr[0] || '-'} ${['一', '二', '三', '四'][arr[1] - 1] + '季度'}`;
                }else if(gv === 'week') {
                    let arr = d.split('-');
                    xv = (arr[0] || '-') + ' ' + arr[1] + '周'
                }
                return xv;
            }),
        }],
        yAxis: [{
            name: yTitle || '纵轴',
            type: 'value',
            nameLocation: (yNameLocation === '' || yNameLocation === null || yNameLocation === undefined) ? 'end' : yNameLocation,
            nameGap: (yNameGap === '' || yNameGap === null || yNameGap === undefined) ? 15 : Number(yNameGap),
            nameRotate: (yNameRotate === '' || yNameRotate === null || yNameRotate === undefined) ? 0 : Number(yNameRotate),
        }],
        series: data.serieses.map(s => {
            return {
                name: !!groupBy && !!groupBy.key ? s.name : yAxis.column.label,
                type: 'line',
                data: s.value.map(v => numberFormat(v)),
                stack: !!groupBy && !!groupBy.key && !!stack,
                label: {
                    normal: {
                        show: !!labelVisible,
                        position: labelPosition || 'inside',
                        distance: (labelDistance === '' || labelDistance === null || labelDistance === undefined) ? 5 : Number(labelDistance),
                        rotate: (labelRotate === '' || labelRotate === null || labelRotate === undefined) ? 0 : Number(labelRotate),
                        formatter: '{c}'
                    }
                },
                symbol: !labelSymbol ? 'emptyCircle' : labelSymbol,
                symbolSize: (labelSymbolSize === '' || labelSymbolSize === null || labelSymbolSize === undefined) ? 4 : Number(labelSymbolSize),
                smooth: !!lineSmooth,
            }
        }),
        dataZoom: {
            show: !!dataZoomVisible
        }
    }, themeConfig);

    let mediaOption = {
        drillDown: drillDown,
        baseOption: option,
        media: EChartsMedia('line', legendVisible, dataZoomVisible, {
            legend: option.legend
        })
    }
    
    return mediaOption;
}

function pieOption(data, pieConfig, themeConfig, styleConfig, drillDown) {
    if(!data) {
        return {
            drillDown
        };
    }
    let { labelHidden } = styleConfig;
    let { xAxis, yAxis } = pieConfig;
    let { tooMany } = data;
    let columnName = xAxis.column.label;
    let dataList = (data.serieses || [{ value: [] }])[0].value;
    let xGranularityV = pieConfig.xAxis.granularity.value;

    //钻取逻辑
    if(drillDown){
        let curDrillDown = drillDown.slice(-1)[0];
        if(curDrillDown.type==='time'){
            xGranularityV = curDrillDown.showDataType
        }else {
            xGranularityV = null;
        }
    }

    let option = deepAssign({
        originConfig: {
            ...pieConfig,
            tooMany,
            data: dataList
        },
        tooltip : {
            trigger: 'item',
            formatter: function(params) {
                let { seriesName, name, value, percent } = params;
                return `${seriesName}:&nbsp;&nbsp;&nbsp;&nbsp;${name}<br/>${yAxis.column.label}:&nbsp;&nbsp;${value}&nbsp;(${percent}%)`;
            }
        },
        grid: {
            left: 50,
            right: 50,
            top: 50,
            bottom: 50,
            containLabel: true
        },
        series : [{
            name: columnName,
            type: 'pie',
            radius: [0, '65%'],
            center: ['50%', '50%'],
            label: {
                normal: {
                    show: labelHidden === undefined ? true : !labelHidden,
                },
                emphasis: {
                    show: true,
                }
            },
            labelLine: {
                normal: {
                    show: labelHidden === undefined ? true : !labelHidden,
                },
                emphasis: {
                    show: true,
                }
            },
            avoidLabelOverlap: labelHidden === undefined ? true : !labelHidden,
            data: dataList.map(v => {
                let obj = { ...v };
                obj.value = numberFormat(obj.value)
                if(!v.name) {
                    obj.name = '空'
                }else if(v.name === '其它') {
                    obj.name = v.name;
                }else {
                    let gv= xGranularityV;
                    if(gv === 'halfYear') {
                        let arr = v.name.split('-H');
                        obj.name = `${arr[0] || '-'} ${['上半年', '下半年'][arr[1] - 1]}`;
                    }else if(gv === 'month') {
                        let arr = v.name.split('-');
                        obj.name = `${arr[0] || '-'}/${arr[1]}`;
                    }else if(gv === 'quarter') {
                        let arr = v.name.split('-');
                        obj.name = `${arr[0] || '-'} ${['一', '二', '三', '四'][arr[1] - 1] + '季度'}`;
                    }else if(gv === 'week') {
                        let arr = v.name.split('-');
                        obj.name = (arr[0] || '-') + ' ' + arr[1] + '周'
                    }
                }
                return obj;
            })
        }]
    }, themeConfig);

    let mediaOption = {
        drillDown: drillDown,
        baseOption: option,
        media: EChartsMedia('pie', true, false, {
            legend: option.legend
        })
    }

    return mediaOption;
}

function scatterOption(data, scatterConfig, themeConfig, styleConfig) {
    const { labelSymbol, xNameLocation, xNameGap, xNameRotate, yNameLocation, yNameGap, yNameRotate, labelSymbolSize, dataZoomVisible } = styleConfig;
    const { xAxis, yAxis, groupBy } = scatterConfig;
    let xTitle = xAxis?`${xAxis.column.label}`:null
    let yTitle = yAxis?`${yAxis.column.label}`:null;
    let hasGroupBy = !!groupBy && !!groupBy.key;
    let legendVisible = hasGroupBy;
    
    let option = deepAssign({
        originConfig: {
            ...scatterConfig
        },
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'cross'
            }
        },
        legend: {
            show: legendVisible
        },
        xAxis : [{
            type : 'value',
            name: xTitle || '横轴',
            nameLocation: (xNameLocation === '' || xNameLocation === null || xNameLocation === undefined) ? 'end' : xNameLocation,
            nameGap: (xNameGap === '' || xNameGap === null || xNameGap === undefined) ? 15 : Number(xNameGap),
            nameRotate: (xNameRotate === '' || xNameRotate === null || xNameRotate === undefined) ? 0 : Number(xNameRotate),
            scale:true,
            splitLine: {
                show: true
            }
        }],
        yAxis : [{
            type : 'value',
            name: yTitle || '纵轴',
            nameLocation: (yNameLocation === '' || yNameLocation === null || yNameLocation === undefined) ? 'end' : yNameLocation,
            nameGap: (yNameGap === '' || yNameGap === null || yNameGap === undefined) ? 15 : Number(yNameGap),
            nameRotate: (yNameRotate === '' || yNameRotate === null || yNameRotate === undefined) ? 0 : Number(yNameRotate),
            scale:true,
            splitLine: {
                show: true
            },
        }],
        series : (data.serieses || []).map(s => {
            return {
                name: s.name,
                type: 'scatter',
                symbol: !labelSymbol ? 'circle' : labelSymbol,
                symbolSize: (labelSymbolSize === '' || labelSymbolSize === null || labelSymbolSize === undefined) ? 10 : Number(labelSymbolSize),
                data: s.mdata.map(m => {
                    return [m.date, numberFormat(m.value)]
                })
            }
        }),
        dataZoom: {
            show: !!dataZoomVisible
        }
    }, themeConfig);

    let mediaOption = {
        baseOption: option,
        media: EChartsMedia('scatter', legendVisible, dataZoomVisible, {
            legend: option.legend
        })
    }
    
    return mediaOption;
}

function aggregateTableOption( data, aggregateTableConfig, themeConfig, styleConfig) {
    const { targetColumn, groupBy, statistics: statisticsNames } = aggregateTableConfig;
    const { direction } = styleConfig;

    let statistics = statisticsNames.map(s => {
            if(!s.name) {
                let f = STATISTICS_OPTION.find(o => o.value === s);
                return !!f ? {
                    name: f.value,
                    label: f.label
                } : null;
            }
            return s
        }).filter(s => !!s),
        group1Name = groupBy.length > 0 ? groupBy[0].key : null,
        group2Name = groupBy.length > 1 ? groupBy[1].key : null,
        group1s = [],
        group2s = [],
        tableData;
    const resData = data.valueList;



    if(!group1Name) { // 无分组
        let o = {};
        statistics.forEach(s => {
            o[s.name] = numberFormat(resData[s.name])
        });
        tableData = o;
    }else {
        if(!group2Name) { // 只有一个分组
            resData.forEach(d => {
                let v = d[group1Name];
                if(group1s.indexOf(v) === -1) {
                    group1s.push(v);
                }
            });
            tableData = resData.map(d => {
                let o = {};
                statistics.forEach(s => {
                    o[s.name] = numberFormat(d[s.name])
                });
                return o;
            });
        }else { // 有两个分组
            resData.forEach(d => {
                let v1 = d[group1Name];
                let v2 = d[group2Name];
                if(group1s.indexOf(v1) === -1) {
                    group1s.push(v1);
                }
                if(group2s.indexOf(v2) === -1) {
                    group2s.push(v2);
                }
            });
            tableData = group1s.map(g => {
                let obj = {},
                    list = resData.filter(d => d[group1Name] === g)
                    // .slice(0, 5);
                
                obj[group1Name] = g;
                obj['data'] = group2s.map(g => {
                    let o = {};
                    o[group2Name] = g;
                    statistics.forEach(s => {
                        let v = list.find(l => l[group2Name] === g);
                        o[s.name] = v ? (typeof v[s.name] === 'number' ? numberFormat(v[s.name]) : '') : '';
                    });
                    return o;
                });
                return obj;
            });

        }
    }

    let option = {
        originConfig: {
            ...aggregateTableConfig
        },
        themeConfig,
        targetColumn,
        direction: direction || 'horizontal',
        group1Name: groupBy.length > 0 ? groupBy[0].key : null,
        group2Name: groupBy.length > 1 ? groupBy[1].key : null,
        group1s,
        group2s,
        statistics,
        data: tableData
    };

    return option;
}

function dataViewOption(data, dataViewConfig, themeConfig, styleConfig) {
    const { list, pageNum, pageSize, pages, total } = data.valueList;
    let { viewColumns } = dataViewConfig;
    let columns = viewColumns || [];
    let dataSource = list || [];

    let option = {
        originConfig: {
            ...dataViewConfig
        },
        themeConfig,
        columns: columns.map(c => {
            let obj = {
                title: c.label,
                dataIndex: c.name,
            }
            if(c.type === 'time') {
                obj.render = (v, r, i) => {
                    let text = v === null ? '空' : moment(v).isValid() ? moment(v).format('YYYY-MM-DD') : v
                    return <EllipsisTooltip title={text}>{text}</EllipsisTooltip>
                }
            }else {
                obj.render = v => {
                    let text = v === null ? '空' : v
                    return <EllipsisTooltip title={text}>{text}</EllipsisTooltip>
                }
            }
            return obj;
        }),
        dataSource: dataSource.map((d, i) => {
            return { ...d, key: i}
        }),
        page: pageNum,
        pageSize,
        pages,
        total,
    };

    return option;
}

function indicatorOption(data, indicatorConfig, themeConfig, styleConfig) {
    const { xAxis, yAxis, otherColumn } = indicatorConfig;
    let option = {
        originConfig: {
            ...indicatorConfig
        },
        themeConfig,
        data: (data.serieses || []).map(d => ({
            name: xAxis.column.value ? (xAxis.column.type === 'time' ? (moment(d.name).isValid() ? moment(d.name).format('YYYY-MM-DD') : d.name) : d.name) : undefined,
            key: `${yAxis.column.label}(${yAxis.gauge.label})`,
            value: d.value,
            others: otherColumn.map(c => ({
                name: c.label,
                value: c.type === 'time' ? (moment(d[c.value]).isValid() ? moment(d[c.value]).format('YYYY-MM-DD') : d[c.value]) : d[c.value]
            }))
        }))
    };

    return option;
}