import React, { memo, useEffect, useMemo, useRef } from 'react';
import { BasicChart } from '@wisdom-components/basicchart';
import optionGenerator, {
    alarmMarkLine,
    specialTypeChartOptionGenerator,
} from './utils';
import { isArray, cloneDeep } from 'lodash';
import moment from "moment";
import patchBIOption from "./useBIMode";
import { BI, Normal } from './theme';
import * as echarts from 'echarts';

echarts.registerTheme('BI', BI)
echarts.registerTheme('Normal', Normal)

const SingleChart = memo((props) => {
    const {
        dataSource,
        contrast = false,
        contrastOption = 'day',
        smooth = true,
        curveCenter,
        showGridLine = true,
        deviceAlarmSchemes,
        chartType,
        lineDataType,
        showBoxOption,
        special,
        predicateData,
        emptyOrError,
        theme = "Normal"
    } = props;
    const chartRef = useRef();
    const timerRef = useRef();
    const SpecialType = ['状态值', '开关值']; // 横向柱状条
    const option = useMemo(() => {
        const config = {
            needUnit: true,
            curveCenter,
            showGridLine,
            deviceAlarmSchemes,
            showMarkLine: true,
            showPoint: true,
            chartType,
            showBoxOption,
            special
        };
        let allValDesc = {};
        let _allSensorType = special?.allSensorType?.reduce((final, curr) => {
            final[curr.id] = curr.type;
            return final;
        }, {});
        let _allPointAddress = special?.allPointAddress?.reduce((final, curr) => {
            final[curr.name] = _allSensorType[curr.sensorTypeID];
            allValDesc[curr.name] = curr.valDesc;
            return final;
        }, {});
        if (dataSource.length === 1 && SpecialType.includes(_allPointAddress[dataSource[0].sensorName])) {
            config.sensorType = _allPointAddress[dataSource[0].sensorName];
            config.special.allValDesc = allValDesc;
            return specialTypeChartOptionGenerator({ dataSource, config });
        }
        let _option = optionGenerator(dataSource, null, contrast, contrastOption, smooth, config, lineDataType, predicateData);
        if (emptyOrError.empty || emptyOrError.error) {
            if (isArray(_option.yAxis)) {
                _option.yAxis.forEach(item => {
                    item.max = 100;
                    item.min = 0;
                })
            } else {
                _option.yAxis.max = 100;
                _option.yAxis.min = 0;
            }
        }
        // 加入bi模式
        if (theme === 'BI') _option = patchBIOption(_option, BI);
        return _option;
    }, [dataSource, smooth, curveCenter, chartType, predicateData]);
    useEffect(() => {
        chartRef.current?.resize?.();
        const chart = chartRef.current?.getEchartsInstance?.();

        function hander(params) {
            const { selected } = params;
            const count = Object.values(selected || {}).filter((item) => item).length;
            const option = cloneDeep(chart.getOption());
            const needMarkLine = count === 1;
            option.series.forEach((item, index) => {
                if (needMarkLine && selected[item.name]) {
                    item.markLine = alarmMarkLine(
                        dataSource[index],
                        index,
                        [dataSource[index]],
                        deviceAlarmSchemes,
                    );
                    // item.markPoint = minMaxMarkPoint(dataSource[index], index, [dataSource[index]]);
                } else {
                    item.markLine = {};
                    item.markPoint = {};
                }
            });
            chart.setOption(option, true);
        }

        function renderMarkPoint(e) {
            if (timerRef.current) clearTimeout(timerRef.current);
            timerRef.current = setTimeout(() => {
                const minMaxMarkPoint = (dataSource) => {
                    // 只有一个数据曲线时显示markline
                    if (dataSource.length !== 1) return {};
                    // 1. 找出最大、最小的值
                    let pointArr = dataSource[0].dataModel;
                    let valueArr = pointArr.map(item => item.pv);
                    let maxValue = Math.max(...valueArr);
                    let minValue = Math.min(...valueArr);
                    // 2. 找出点的索引和实际的点
                    let maxValueIndex = valueArr.findIndex(val => val === maxValue);
                    let minValueIndex = valueArr.findIndex(val => val === minValue);
                    let maxPoint = pointArr[maxValueIndex];
                    let minPoint = pointArr[minValueIndex];
                    if (!maxPoint || !minPoint) return {}
                    // 3. 计算坐标位置，返回的是 [x,y]的像素坐标
                    let maxPointPosition = chart.convertToPixel({ seriesIndex: 0 }, [moment(maxPoint.pt).valueOf(), maxPoint.pv])
                    let minPointPosition = chart.convertToPixel({ seriesIndex: 0 }, [moment(minPoint.pt).valueOf(), minPoint.pv])
                    if (!maxPointPosition || !minPointPosition) return;
                    // 4. 计算最大最小值的标签宽度
                    let maxLength = 80 + String(maxValue).length * 5;
                    let minLength = 80 + String(minValue).length * 5;
                    // 5. 获取实例的宽度
                    let chartWidth = chart.getWidth();
                    // 6. 确定是否超出边界，确定超出边界是哪一边；
                    let maxTagLeft = maxPointPosition[0] - maxLength / 2;
                    let maxTagRight = maxPointPosition[0] + maxLength / 2;
                    let minTagLeft = minPointPosition[0] - minLength / 2;
                    let minTagRight = minPointPosition[0] + minLength / 2;
                    let maxOutEdge = false, minOutEdge = false;
                    let maxOutSide = '', minOutSide = '';

                    // 在实际使用中，我们认为不存在一个tag同时超出边界的情况。
                    if (maxTagLeft < 0) {
                        maxOutEdge = true;
                        maxOutSide = 'left';
                    }
                    if (maxTagRight > chartWidth) {
                        maxOutEdge = true;
                        maxOutSide = 'right';
                    }

                    if (minTagLeft < 0) {
                        minOutEdge = true;
                        minOutSide = 'left';
                    }
                    if (minTagRight > chartWidth) {
                        minOutEdge = true;
                        minOutSide = 'right';
                    }
                    // 7. 确定使用的图形
                    // 默认图形，居中
                    let maxIconPath = `path://M1233.329493 195.75466633h-1112.064c-34.128213 0-61.781333 27.661653-61.781333 61.781334v473.658026c0 34.117973 27.65312 61.781333 61.781333 61.781334h472.80128l83.23072 144.155306 83.23072-144.155306h472.80128c34.128213 0 61.781333-27.66336 61.781334-61.781334V257.53600033c0-34.117973-27.65312-61.781333-61.781334-61.781334z`;
                    let maxSymbolOffset = [0, -20];
                    if (maxOutEdge) {
                        if (maxOutSide === 'left') {
                            // 左边界超出，使用朝右的图表
                            maxSymbolOffset = ['50%', -20];
                            maxIconPath = 'path://M48.677,6.151v10c0,1.7-1.3,3-3,3h-35.5l-6.7,4c0,0,0.2-5.3,0.2-7v-10c0-1.7,1.3-3,3-3h39C47.277,3.151,48.677,4.551,48.677,6.151z';
                        } else if (maxOutSide === 'right') {
                            // 右边界超出，使用朝左的图表
                            maxSymbolOffset = ['-50%', -20];
                            maxIconPath = 'path://M6.477,3.151h39c1.7,0,3,1.3,3,3v10c0,1.7,0.2,7,0.2,7l-6.7-4h-35.5c-1.7,0-3-1.3-3-3v-10C3.477,4.551,4.877,3.151,6.477,3.151z'
                        }
                    }
                    // 默认图形
                    let minIconPath = 'path://M131.999 849.579h1112.064c34.128 0 61.781-27.662 61.781-61.781v-473.658c0-34.118-27.653-61.781-61.781-61.781h-472.801l-83.231-144.155-83.231 144.155h-472.801c-34.128 0-61.781 27.663-61.781 61.781v473.658c0 34.118 27.653 61.781 61.781 61.781z';
                    let minSymbolOffset = [0, 20];
                    if (minOutEdge) {
                        if (minOutSide === 'left') {
                            // 左边界超出，使用朝右的图表
                            minSymbolOffset = ['50%', 20];
                            minIconPath = 'path://M45.677,23.151h-39c-1.7,0-3-1.3-3-3v-10c0-1.7-0.2-7-0.2-7l6.7,4h35.5c1.7,0,3,1.3,3,3v10C48.677,21.751,47.277,23.151,45.677,23.151z';
                        } else if (minOutSide === 'right') {
                            // 右边界超出，使用朝左的图表
                            minSymbolOffset = ['-50%', 20];
                            minIconPath = 'path://M3.477,20.151v-10c0-1.7,1.3-3,3-3h35.5l6.7-4c0,0-0.2,5.3-0.2,7v10c0,1.7-1.3,3-3,3h-39C4.877,23.151,3.477,21.751,3.477,20.151z'
                        }
                    }

                    const data = [
                        {
                            type: 'min',
                            color: 'rgba(255,255,255,1)',
                            name: '最小: ',
                            symbolOffset: minSymbolOffset,
                            symbol: minIconPath,
                            symbolSize: (e) => {
                                let str = ![undefined, null].includes(e) ? String(e) : '';
                                let length = 60 + str.length * 6
                                return [length, 32]
                            },
                            label: {
                                show: true,
                                color: '#fff',
                                formatter: '最小: {c}',
                                fontSize: 14,
                                fontWeight: 'bold',
                                verticalAlign: 'top',
                                offset: [0, -2]
                            },
                            itemStyle: {
                                // color: "#21c8c3",
                            }
                        },
                        {
                            type: 'max',
                            name: '最大: ',
                            position: [20, 200],
                            symbol: maxIconPath,
                            symbolOffset: maxSymbolOffset,
                            symbolSize: (e) => {
                                let str = ![undefined, null].includes(e) ? String(e) : '';
                                let length = 60 + str.length * 6
                                return [length, 32]
                            },
                            itemStyle: {
                                // color: "#1980ff",
                            },
                            label: {
                                color: '#fff',
                                fontSize: 14,
                                fontWeight: 'bold',
                                show: true,
                                formatter: '最大: {c}',
                                offset: [0, -2]
                            }
                        },
                        {
                            name: '',
                            type: 'max',
                            symbol: 'emptyCircle',
                            label: { show: false },
                            symbolSize: 6,
                        },
                        {
                            name: '',
                            type: 'min',
                            symbol: 'emptyCircle',
                            label: { show: false },
                            symbolSize: 6,
                        }
                    ];
                    return {
                        symbol: 'circle',
                        symbolSize: 20,
                        animation: false,
                        silent: true,
                        label: {
                            show: false,
                        },
                        data,
                    };
                };
                // minMaxMarkPoint(dataSource)
                chart.setOption({ series: { markPoint: minMaxMarkPoint(dataSource) } })
            }, 200)
        }

        if (!chart) return;
        renderMarkPoint();
        chart.on('legendselectchanged', hander);
        chart.on('legendselectchanged', renderMarkPoint);
        chart.on('datazoom', renderMarkPoint);
        return () => {
            chart.off('legendselectchanged', hander);
            chart.off('legendselectchanged', renderMarkPoint);
            chart.off('datazoom', renderMarkPoint);
        };
    }, [dataSource, deviceAlarmSchemes]);

    // 网格开关，不更新整个图表
    useEffect(() => {
        const chart = chartRef.current?.getEchartsInstance?.();
        if (!chart) return;
        const option = chart.getOption();
        // 交互指针
        const tooltip = {
            trigger: 'axis',
            axisPointer: {
                type: showGridLine ? 'cross' : 'line',
            },
        };
        // 网格线
        const axisConfig = {
            minorTick: {
                show: showGridLine,
                splitNumber: 2,
            },
            minorSplitLine: {
                // show: showGridLine,
                show: theme === 'BI' ? false : showGridLine,
                lineStyle: {
                    type: 'dashed',
                },
            },
            splitLine: {
                show: showGridLine,
            },
        };
        let yAxis = axisConfig;
        if (isArray(option.yAxis)) {
            yAxis = option.yAxis.map((item) => ({ ...axisConfig }));
        }
        let xAxis = axisConfig;
        chart.setOption({
            xAxis,
            yAxis,
            tooltip,
        });
    }, [showGridLine]);
    return <BasicChart theme={theme} ref={chartRef} option={option} notMerge
        style={{ width: '100%', height: '100%' }} />
});

export default SingleChart;
