/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {bind, each, isFunction, isString, indexOf} from 'zrender/src/core/util';
import * as eventTool from 'zrender/src/core/event';
import * as graphic from '../../util/graphic';
import * as throttle from '../../util/throttle';
import DataZoomView from './DataZoomView';
import {linearMap, asc, parsePercent} from '../../util/number';
import * as layout from '../../util/layout';
import sliderMove from '../helper/sliderMove';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import {
    LayoutOrient, Payload, ZRTextVerticalAlign, ZRTextAlign, ZRElementEvent, ParsedValue
} from '../../util/types';
import SliderZoomModel from './SliderZoomModel';
import { RectLike } from 'zrender/src/core/BoundingRect';
import Axis from '../../coord/Axis';
import SeriesModel from '../../model/Series';
import { AxisBaseModel } from '../../coord/AxisBaseModel';
import { getAxisMainType, collectReferCoordSysModelInfo } from './helper';
import { enableHoverEmphasis } from '../../util/states';
import { createSymbol, symbolBuildProxies } from '../../util/symbol';
import { deprecateLog } from '../../util/log';
import { PointLike } from 'zrender/src/core/Point';
import Displayable from 'zrender/src/graphic/Displayable';
import {createTextStyle} from '../../label/labelStyle';

const Rect = graphic.Rect;

// Constants
const DEFAULT_LOCATION_EDGE_GAP = 7;
const DEFAULT_FRAME_BORDER_WIDTH = 1;
const DEFAULT_FILLER_SIZE = 30;
const DEFAULT_MOVE_HANDLE_SIZE = 7;
const HORIZONTAL = 'horizontal';
const VERTICAL = 'vertical';
const LABEL_GAP = 5;
const SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter'];

const REALTIME_ANIMATION_CONFIG = {
    easing: 'cubicOut',
    duration: 100,
    delay: 0
} as const;

// const NORMAL_ANIMATION_CONFIG = {
//     easing: 'cubicInOut',
//     duration: 200
// } as const;


interface Displayables {
    sliderGroup: graphic.Group;
    handles: [graphic.Path, graphic.Path];
    handleLabels: [graphic.Text, graphic.Text];
    dataShadowSegs: graphic.Group[];
    filler: graphic.Rect;

    brushRect: graphic.Rect;

    moveHandle: graphic.Rect;
    moveHandleIcon: graphic.Path;
    // invisible move zone.
    moveZone: graphic.Rect;
}
class SliderZoomView extends DataZoomView {
    static type = 'dataZoom.slider';
    type = SliderZoomView.type;

    dataZoomModel: SliderZoomModel;

    private _displayables = {} as Displayables;

    private _orient: LayoutOrient;

    private _range: number[];

    /**
     * [coord of the first handle, coord of the second handle]
     */
    private _handleEnds: number[];

    /**
     * [length, thick]
     */
    private _size: number[];

    private _handleWidth: number;

    private _handleHeight: number;

    private _location: PointLike;

    private _brushStart: PointLike;
    private _brushStartTime: number;

    private _dragging: boolean;

    private _brushing: boolean;

    private _dataShadowInfo: {
        thisAxis: Axis
        series: SeriesModel
        thisDim: string
        otherDim: string
        otherAxisInverse: boolean
    };

    init(ecModel: GlobalModel, api: ExtensionAPI) {
        this.api = api;

        // A unique handler for each dataZoom component
        this._onBrush = bind(this._onBrush, this);
        this._onBrushEnd = bind(this._onBrushEnd, this);
    }

    render(
        dataZoomModel: SliderZoomModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: Payload & {
            from: string
            type: string
        }
    ) {
        super.render.apply(this, arguments as any);

        throttle.createOrUpdate(
            this,
            '_dispatchZoomAction',
            dataZoomModel.get('throttle'),
            'fixRate'
        );

        this._orient = dataZoomModel.getOrient();

        if (dataZoomModel.get('show') === false) {
            this.group.removeAll();
            return;
        }

        if (dataZoomModel.noTarget()) {
            this._clear();
            this.group.removeAll();
            return;
        }

        // Notice: this._resetInterval() should not be executed when payload.type
        // is 'dataZoom', origin this._range should be maintained, otherwise 'pan'
        // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction,
        if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
            this._buildView();
        }

        this._updateView();
    }

    dispose() {
        this._clear();
        super.dispose.apply(this, arguments as any);
    }

    private _clear() {
        throttle.clear(this, '_dispatchZoomAction');

        const zr = this.api.getZr();
        zr.off('mousemove', this._onBrush);
        zr.off('mouseup', this._onBrushEnd);
    }

    private _buildView() {
        const thisGroup = this.group;

        thisGroup.removeAll();

        this._brushing = false;
        this._displayables.brushRect = null;

        this._resetLocation();
        this._resetInterval();

        const barGroup = this._displayables.sliderGroup = new graphic.Group();

        this._renderBackground();

        this._renderHandle();

        this._renderDataShadow();

        thisGroup.add(barGroup);

        this._positionGroup();
    }

    private _resetLocation() {
        const dataZoomModel = this.dataZoomModel;
        const api = this.api;
        const showMoveHandle = dataZoomModel.get('brushSelect');
        const moveHandleSize = showMoveHandle ? DEFAULT_MOVE_HANDLE_SIZE : 0;

        // If some of x/y/width/height are not specified,
        // auto-adapt according to target grid.
        const coordRect = this._findCoordRect();
        const ecSize = {width: api.getWidth(), height: api.getHeight()};
        // Default align by coordinate system rect.
        const positionInfo = this._orient === HORIZONTAL
            ? {
                // Why using 'right', because right should be used in vertical,
                // and it is better to be consistent for dealing with position param merge.
                right: ecSize.width - coordRect.x - coordRect.width,
                top: (ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP - moveHandleSize),
                width: coordRect.width,
                height: DEFAULT_FILLER_SIZE
            }
            : { // vertical
                right: DEFAULT_LOCATION_EDGE_GAP,
                top: coordRect.y,
                width: DEFAULT_FILLER_SIZE,
                height: coordRect.height
            };

        // Do not write back to option and replace value 'ph', because
        // the 'ph' value should be recalculated when resize.
        const layoutParams = layout.getLayoutParams(dataZoomModel.option);

        // Replace the placeholder value.
        each(['right', 'top', 'width', 'height'] as const, function (name) {
            if (layoutParams[name] === 'ph') {
                layoutParams[name] = positionInfo[name];
            }
        });

        const layoutRect = layout.getLayoutRect(
            layoutParams,
            ecSize
        );

        this._location = {x: layoutRect.x, y: layoutRect.y};
        this._size = [layoutRect.width, layoutRect.height];
        this._orient === VERTICAL && this._size.reverse();
    }

    private _positionGroup() {
        const thisGroup = this.group;
        const location = this._location;
        const orient = this._orient;

        // Just use the first axis to determine mapping.
        const targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel();
        const inverse = targetAxisModel && targetAxisModel.get('inverse');

        const sliderGroup = this._displayables.sliderGroup;
        const otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse;

        // Transform barGroup.
        sliderGroup.attr(
            (orient === HORIZONTAL && !inverse)
            ? {scaleY: otherAxisInverse ? 1 : -1, scaleX: 1 }
            : (orient === HORIZONTAL && inverse)
            ? {scaleY: otherAxisInverse ? 1 : -1, scaleX: -1 }
            : (orient === VERTICAL && !inverse)
            ? {scaleY: otherAxisInverse ? -1 : 1, scaleX: 1, rotation: Math.PI / 2}
            // Dont use Math.PI, considering shadow direction.
            : {scaleY: otherAxisInverse ? -1 : 1, scaleX: -1, rotation: Math.PI / 2}
        );

        // Position barGroup
        const rect = thisGroup.getBoundingRect([sliderGroup]);
        thisGroup.x = location.x - rect.x;
        thisGroup.y = location.y - rect.y;
        thisGroup.markRedraw();
    }

    private _getViewExtent() {
        return [0, this._size[0]];
    }

    private _renderBackground() {
        const dataZoomModel = this.dataZoomModel;
        const size = this._size;
        const barGroup = this._displayables.sliderGroup;
        const brushSelect = dataZoomModel.get('brushSelect');

        barGroup.add(new Rect({
            silent: true,
            shape: {
                x: 0, y: 0, width: size[0], height: size[1]
            },
            style: {
                fill: dataZoomModel.get('backgroundColor')
            },
            z2: -40
        }));

        // Click panel, over shadow, below handles.
        const clickPanel = new Rect({
            shape: {
                x: 0, y: 0, width: size[0], height: size[1]
            },
            style: {
                fill: 'transparent'
            },
            z2: 0,
            onclick: bind(this._onClickPanel, this)
        });

        const zr = this.api.getZr();
        if (brushSelect) {
            clickPanel.on('mousedown', this._onBrushStart, this);
            clickPanel.cursor = 'crosshair';

            zr.on('mousemove', this._onBrush);
            zr.on('mouseup', this._onBrushEnd);
        }
        else {
            zr.off('mousemove', this._onBrush);
            zr.off('mouseup', this._onBrushEnd);
        }

        barGroup.add(clickPanel);
    }

    private _renderDataShadow() {
        const info = this._dataShadowInfo = this._prepareDataShadowInfo();

        this._displayables.dataShadowSegs = [];

        if (!info) {
            return;
        }

        const size = this._size;
        const seriesModel = info.series;
        const data = seriesModel.getRawData();

        const otherDim: string = seriesModel.getShadowDim
            ? seriesModel.getShadowDim() // @see candlestick
            : info.otherDim;

        if (otherDim == null) {
            return;
        }

        let otherDataExtent = data.getDataExtent(otherDim);
        // Nice extent.
        const otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
        otherDataExtent = [
            otherDataExtent[0] - otherOffset,
            otherDataExtent[1] + otherOffset
        ];
        const otherShadowExtent = [0, size[1]];

        const thisShadowExtent = [0, size[0]];

        const areaPoints = [[size[0], 0], [0, 0]];
        const linePoints: number[][] = [];
        const step = thisShadowExtent[1] / (data.count() - 1);
        let thisCoord = 0;

        // Optimize for large data shadow
        const stride = Math.round(data.count() / size[0]);
        let lastIsEmpty: boolean;
        data.each([otherDim], function (value: ParsedValue, index) {
            if (stride > 0 && (index % stride)) {
                thisCoord += step;
                return;
            }

            // FIXME
            // Should consider axis.min/axis.max when drawing dataShadow.

            // FIXME
            // 应该使用统一的空判断？还是在list里进行空判断？
            const isEmpty = value == null || isNaN(value as number) || value === '';
            // See #4235.
            const otherCoord = isEmpty
                ? 0 : linearMap(value as number, otherDataExtent, otherShadowExtent, true);

            // Attempt to draw data shadow precisely when there are empty value.
            if (isEmpty && !lastIsEmpty && index) {
                areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
                linePoints.push([linePoints[linePoints.length - 1][0], 0]);
            }
            else if (!isEmpty && lastIsEmpty) {
                areaPoints.push([thisCoord, 0]);
                linePoints.push([thisCoord, 0]);
            }

            areaPoints.push([thisCoord, otherCoord]);
            linePoints.push([thisCoord, otherCoord]);

            thisCoord += step;
            lastIsEmpty = isEmpty;
        });

        const dataZoomModel = this.dataZoomModel;

        function createDataShadowGroup(isSelectedArea?: boolean) {
            const model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground');
            const group = new graphic.Group();
            const polygon = new graphic.Polygon({
                shape: {points: areaPoints},
                segmentIgnoreThreshold: 1,
                style: model.getModel('areaStyle').getAreaStyle(),
                silent: true,
                z2: -20
            });
            const polyline = new graphic.Polyline({
                shape: {points: linePoints},
                segmentIgnoreThreshold: 1,
                style: model.getModel('lineStyle').getLineStyle(),
                silent: true,
                z2: -19
            });
            group.add(polygon);
            group.add(polyline);
            return group;
        }

        // let dataBackgroundModel = dataZoomModel.getModel('dataBackground');
        for (let i = 0; i < 3; i++) {
            const group = createDataShadowGroup(i === 1);
            this._displayables.sliderGroup.add(group);
            this._displayables.dataShadowSegs.push(group);
        }
    }

    private _prepareDataShadowInfo() {
        const dataZoomModel = this.dataZoomModel;
        const showDataShadow = dataZoomModel.get('showDataShadow');

        if (showDataShadow === false) {
            return;
        }

        // Find a representative series.
        let result: SliderZoomView['_dataShadowInfo'];
        const ecModel = this.ecModel;

        dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) {
            const seriesModels = dataZoomModel
                .getAxisProxy(axisDim, axisIndex)
                .getTargetSeriesModels();

            each(seriesModels, function (seriesModel) {
                if (result) {
                    return;
                }

                if (showDataShadow !== true && indexOf(
                        SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')
                    ) < 0
                ) {
                    return;
                }

                const thisAxis = (
                    ecModel.getComponent(getAxisMainType(axisDim), axisIndex) as AxisBaseModel
                ).axis;
                let otherDim = getOtherDim(axisDim);
                let otherAxisInverse;
                const coordSys = seriesModel.coordinateSystem;

                if (otherDim != null && coordSys.getOtherAxis) {
                    otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse;
                }

                otherDim = seriesModel.getData().mapDimension(otherDim);

                result = {
                    thisAxis: thisAxis,
                    series: seriesModel,
                    thisDim: axisDim,
                    otherDim: otherDim,
                    otherAxisInverse: otherAxisInverse
                };

            }, this);

        }, this);

        return result;
    }

    private _renderHandle() {
        const thisGroup = this.group;
        const displayables = this._displayables;
        const handles: [graphic.Path, graphic.Path] = displayables.handles = [null, null];
        const handleLabels: [graphic.Text, graphic.Text] = displayables.handleLabels = [null, null];
        const sliderGroup = this._displayables.sliderGroup;
        const size = this._size;
        const dataZoomModel = this.dataZoomModel;
        const api = this.api;

        const borderRadius = dataZoomModel.get('borderRadius') || 0;

        const brushSelect = dataZoomModel.get('brushSelect');

        const filler = displayables.filler = new Rect({
            silent: brushSelect,
            style: {
                fill: dataZoomModel.get('fillerColor')
            },
            textConfig: {
                position: 'inside'
            }
        });

        sliderGroup.add(filler);

        // Frame border.
        sliderGroup.add(new Rect({
            silent: true,
            subPixelOptimize: true,
            shape: {
                x: 0,
                y: 0,
                width: size[0],
                height: size[1],
                r: borderRadius
            },
            style: {
                stroke: dataZoomModel.get('dataBackgroundColor' as any) // deprecated option
                    || dataZoomModel.get('borderColor'),
                lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
                fill: 'rgba(0,0,0,0)'
            }
        }));

        // Left and right handle to resize
        each([0, 1] as const, function (handleIndex) {
            let iconStr = dataZoomModel.get('handleIcon');
            if (
                !symbolBuildProxies[iconStr]
                && iconStr.indexOf('path://') < 0
                && iconStr.indexOf('image://') < 0
            ) {
                // Compatitable with the old icon parsers. Which can use a path string without path://
                iconStr = 'path://' + iconStr;
                if (__DEV__) {
                    deprecateLog('handleIcon now needs \'path://\' prefix when using a path string');
                }
            }
            const path = createSymbol(
                iconStr,
                -1, 0, 2, 2, null, true
            ) as graphic.Path;
            path.attr({
                cursor: getCursor(this._orient),
                draggable: true,
                drift: bind(this._onDragMove, this, handleIndex),
                ondragend: bind(this._onDragEnd, this),
                onmouseover: bind(this._showDataInfo, this, true),
                onmouseout: bind(this._showDataInfo, this, false),
                z2: 5
            });

            const bRect = path.getBoundingRect();
            const handleSize = dataZoomModel.get('handleSize');

            this._handleHeight = parsePercent(handleSize, this._size[1]);
            this._handleWidth = bRect.width / bRect.height * this._handleHeight;

            path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle());
            path.style.strokeNoScale = true;
            path.rectHover = true;

            path.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'handleStyle']).getItemStyle();
            enableHoverEmphasis(path);

            const handleColor = dataZoomModel.get('handleColor' as any); // deprecated option
            // Compatitable with previous version
            if (handleColor != null) {
                path.style.fill = handleColor;
            }

            sliderGroup.add(handles[handleIndex] = path);

            const textStyleModel = dataZoomModel.getModel('textStyle');

            thisGroup.add(
                handleLabels[handleIndex] = new graphic.Text({
                silent: true,
                invisible: true,
                style: createTextStyle(textStyleModel, {
                    x: 0, y: 0, text: '',
                    verticalAlign: 'middle',
                    align: 'center',
                    fill: textStyleModel.getTextColor(),
                    font: textStyleModel.getFont()
                }),
                z2: 10
            }));

        }, this);

        // Handle to move. Only visible when brushSelect is set true.
        let actualMoveZone: Displayable = filler;
        if (brushSelect) {
            const moveHandleHeight = parsePercent(dataZoomModel.get('moveHandleSize'), size[1]);
            const moveHandle = displayables.moveHandle = new graphic.Rect({
                style: dataZoomModel.getModel('moveHandleStyle').getItemStyle(),
                silent: true,
                shape: {
                    r: [0, 0, 2, 2],
                    y: size[1] - 0.5,
                    height: moveHandleHeight
                }
            });
            const iconSize = moveHandleHeight * 0.8;
            const moveHandleIcon = displayables.moveHandleIcon = createSymbol(
                dataZoomModel.get('moveHandleIcon'),
                -iconSize / 2, -iconSize / 2, iconSize, iconSize,
                '#fff',
                true
            );
            moveHandleIcon.silent = true;
            moveHandleIcon.y = size[1] + moveHandleHeight / 2 - 0.5;

            moveHandle.ensureState('emphasis').style = dataZoomModel.getModel(
                ['emphasis', 'moveHandleStyle']
            ).getItemStyle();

            const moveZoneExpandSize = Math.min(size[1] / 2, Math.max(moveHandleHeight, 10));
            actualMoveZone = displayables.moveZone = new graphic.Rect({
                invisible: true,
                shape: {
                    y: size[1] - moveZoneExpandSize,
                    height: moveHandleHeight + moveZoneExpandSize
                }
            });

            actualMoveZone.on('mouseover', () => {
                    api.enterEmphasis(moveHandle);
                })
                .on('mouseout', () => {
                    api.leaveEmphasis(moveHandle);
                });

            sliderGroup.add(moveHandle);
            sliderGroup.add(moveHandleIcon);
            sliderGroup.add(actualMoveZone);
        }

        actualMoveZone.attr({
            draggable: true,
            cursor: getCursor(this._orient),
            drift: bind(this._onDragMove, this, 'all'),
            ondragstart: bind(this._showDataInfo, this, true),
            ondragend: bind(this._onDragEnd, this),
            onmouseover: bind(this._showDataInfo, this, true),
            onmouseout: bind(this._showDataInfo, this, false)
        });
    }

    private _resetInterval() {
        const range = this._range = this.dataZoomModel.getPercentRange();
        const viewExtent = this._getViewExtent();

        this._handleEnds = [
            linearMap(range[0], [0, 100], viewExtent, true),
            linearMap(range[1], [0, 100], viewExtent, true)
        ];
    }

    private _updateInterval(handleIndex: 0 | 1 | 'all', delta: number): boolean {
        const dataZoomModel = this.dataZoomModel;
        const handleEnds = this._handleEnds;
        const viewExtend = this._getViewExtent();
        const minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
        const percentExtent = [0, 100];

        sliderMove(
            delta,
            handleEnds,
            viewExtend,
            dataZoomModel.get('zoomLock') ? 'all' : handleIndex,
            minMaxSpan.minSpan != null
                ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null,
            minMaxSpan.maxSpan != null
                ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null
        );

        const lastRange = this._range;
        const range = this._range = asc([
            linearMap(handleEnds[0], viewExtend, percentExtent, true),
            linearMap(handleEnds[1], viewExtend, percentExtent, true)
        ]);

        return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1];
    }

    private _updateView(nonRealtime?: boolean) {
        const displaybles = this._displayables;
        const handleEnds = this._handleEnds;
        const handleInterval = asc(handleEnds.slice());
        const size = this._size;

        each([0, 1] as const, function (handleIndex) {
            // Handles
            const handle = displaybles.handles[handleIndex];
            const handleHeight = this._handleHeight;
            (handle as graphic.Path).attr({
                scaleX: handleHeight / 2,
                scaleY: handleHeight / 2,
                // This is a trick, by adding an extra tiny offset to let the default handle's end point align to the drag window.
                // NOTE: It may affect some custom shapes a bit. But we prefer to have better result by default.
                x: handleEnds[handleIndex] + (handleIndex ? -1 : 1),
                y: size[1] / 2 - handleHeight / 2
            });
        }, this);

        // Filler
        displaybles.filler.setShape({
            x: handleInterval[0],
            y: 0,
            width: handleInterval[1] - handleInterval[0],
            height: size[1]
        });

        const viewExtent = {
            x: handleInterval[0],
            width: handleInterval[1] - handleInterval[0]
        };
        // Move handle
        if (displaybles.moveHandle) {
            displaybles.moveHandle.setShape(viewExtent);
            displaybles.moveZone.setShape(viewExtent);
            // Force update path on the invisible object
            displaybles.moveZone.getBoundingRect();
            displaybles.moveHandleIcon && displaybles.moveHandleIcon.attr('x', viewExtent.x + viewExtent.width / 2);
        }

        // update clip path of shadow.
        const dataShadowSegs = displaybles.dataShadowSegs;
        const segIntervals = [0, handleInterval[0], handleInterval[1], size[0]];

        for (let i = 0; i < dataShadowSegs.length; i++) {
            const segGroup = dataShadowSegs[i];
            let clipPath = segGroup.getClipPath();
            if (!clipPath) {
                clipPath = new graphic.Rect();
                segGroup.setClipPath(clipPath);
            }
            clipPath.setShape({
                x: segIntervals[i],
                y: 0,
                width: segIntervals[i + 1] - segIntervals[i],
                height: size[1]
            });
        }

        this._updateDataInfo(nonRealtime);
    }

    private _updateDataInfo(nonRealtime?: boolean) {
        const dataZoomModel = this.dataZoomModel;
        const displaybles = this._displayables;
        const handleLabels = displaybles.handleLabels;
        const orient = this._orient;
        let labelTexts = ['', ''];

        // FIXME
        // date型，支持formatter，autoformatter（ec2 date.getAutoFormatter）
        if (dataZoomModel.get('showDetail')) {
            const axisProxy = dataZoomModel.findRepresentativeAxisProxy();

            if (axisProxy) {
                const axis = axisProxy.getAxisModel().axis;
                const range = this._range;

                const dataInterval = nonRealtime
                    // See #4434, data and axis are not processed and reset yet in non-realtime mode.
                    ? axisProxy.calculateDataWindow({
                        start: range[0], end: range[1]
                    }).valueWindow
                    : axisProxy.getDataValueWindow();

                labelTexts = [
                    this._formatLabel(dataInterval[0], axis),
                    this._formatLabel(dataInterval[1], axis)
                ];
            }
        }

        const orderedHandleEnds = asc(this._handleEnds.slice());

        setLabel.call(this, 0);
        setLabel.call(this, 1);

        function setLabel(this: SliderZoomView, handleIndex: 0 | 1) {
            // Label
            // Text should not transform by barGroup.
            // Ignore handlers transform
            const barTransform = graphic.getTransform(
                displaybles.handles[handleIndex].parent, this.group
            );
            const direction = graphic.transformDirection(
                handleIndex === 0 ? 'right' : 'left', barTransform
            );
            const offset = this._handleWidth / 2 + LABEL_GAP;
            const textPoint = graphic.applyTransform(
                [
                    orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset),
                    this._size[1] / 2
                ],
                barTransform
            );
            handleLabels[handleIndex].setStyle({
                x: textPoint[0],
                y: textPoint[1],
                verticalAlign: orient === HORIZONTAL ? 'middle' : direction as ZRTextVerticalAlign,
                align: orient === HORIZONTAL ? direction as ZRTextAlign : 'center',
                text: labelTexts[handleIndex]
            });
        }
    }

    private _formatLabel(value: ParsedValue, axis: Axis) {
        const dataZoomModel = this.dataZoomModel;
        const labelFormatter = dataZoomModel.get('labelFormatter');

        let labelPrecision = dataZoomModel.get('labelPrecision');
        if (labelPrecision == null || labelPrecision === 'auto') {
            labelPrecision = axis.getPixelPrecision();
        }

        const valueStr = (value == null || isNaN(value as number))
            ? ''
            // FIXME Glue code
            : (axis.type === 'category' || axis.type === 'time')
                ? axis.scale.getLabel({
                    value: Math.round(value as number)
                })
                // param of toFixed should less then 20.
                : (value as number).toFixed(Math.min(labelPrecision as number, 20));

        return isFunction(labelFormatter)
            ? labelFormatter(value as number, valueStr)
            : isString(labelFormatter)
            ? labelFormatter.replace('{value}', valueStr)
            : valueStr;
    }

    /**
     * @param showOrHide true: show, false: hide
     */
    private _showDataInfo(showOrHide?: boolean) {
        // Always show when drgging.
        showOrHide = this._dragging || showOrHide;
        const displayables = this._displayables;
        const handleLabels = displayables.handleLabels;
        handleLabels[0].attr('invisible', !showOrHide);
        handleLabels[1].attr('invisible', !showOrHide);

        // Highlight move handle
        displayables.moveHandle
            && this.api[showOrHide ? 'enterEmphasis' : 'leaveEmphasis'](displayables.moveHandle, 1);
    }

    private _onDragMove(handleIndex: 0 | 1 | 'all', dx: number, dy: number, event: ZRElementEvent) {
        this._dragging = true;

        // For mobile device, prevent screen slider on the button.
        eventTool.stop(event.event);

        // Transform dx, dy to bar coordination.
        const barTransform = this._displayables.sliderGroup.getLocalTransform();
        const vertex = graphic.applyTransform([dx, dy], barTransform, true);

        const changed = this._updateInterval(handleIndex, vertex[0]);

        const realtime = this.dataZoomModel.get('realtime');

        this._updateView(!realtime);

        // Avoid dispatch dataZoom repeatly but range not changed,
        // which cause bad visual effect when progressive enabled.
        changed && realtime && this._dispatchZoomAction(true);
    }

    private _onDragEnd() {
        this._dragging = false;
        this._showDataInfo(false);

        // While in realtime mode and stream mode, dispatch action when
        // drag end will cause the whole view rerender, which is unnecessary.
        const realtime = this.dataZoomModel.get('realtime');
        !realtime && this._dispatchZoomAction(false);
    }

    private _onClickPanel(e: ZRElementEvent) {
        const size = this._size;
        const localPoint = this._displayables.sliderGroup.transformCoordToLocal(e.offsetX, e.offsetY);

        if (localPoint[0] < 0 || localPoint[0] > size[0]
            || localPoint[1] < 0 || localPoint[1] > size[1]
        ) {
            return;
        }

        const handleEnds = this._handleEnds;
        const center = (handleEnds[0] + handleEnds[1]) / 2;

        const changed = this._updateInterval('all', localPoint[0] - center);
        this._updateView();
        changed && this._dispatchZoomAction(false);
    }

    private _onBrushStart(e: ZRElementEvent) {
        const x = e.offsetX;
        const y = e.offsetY;
        this._brushStart = new graphic.Point(x, y);

        this._brushing = true;

        this._brushStartTime = +new Date();
        // this._updateBrushRect(x, y);
    }

    private _onBrushEnd(e: ZRElementEvent) {
        if (!this._brushing) {
            return;
        }

        const brushRect = this._displayables.brushRect;
        this._brushing = false;

        if (!brushRect) {
            return;
        }

        brushRect.attr('ignore', true);

        const brushShape = brushRect.shape;

        const brushEndTime = +new Date();
        // console.log(brushEndTime - this._brushStartTime);
        if (brushEndTime - this._brushStartTime < 200 && Math.abs(brushShape.width) < 5) {
            // Will treat it as a click
            return;
        }

        const viewExtend = this._getViewExtent();
        const percentExtent = [0, 100];

        this._range = asc([
            linearMap(brushShape.x, viewExtend, percentExtent, true),
            linearMap(brushShape.x + brushShape.width, viewExtend, percentExtent, true)
        ]);

        this._handleEnds = [brushShape.x, brushShape.x + brushShape.width];

        this._updateView();

        this._dispatchZoomAction(false);
    }

    private _onBrush(e: ZRElementEvent) {
        if (this._brushing) {
            // For mobile device, prevent screen slider on the button.
            eventTool.stop(e.event);

            this._updateBrushRect(e.offsetX, e.offsetY);
        }
    }

    private _updateBrushRect(mouseX: number, mouseY: number) {
        const displayables = this._displayables;
        const dataZoomModel = this.dataZoomModel;
        let brushRect = displayables.brushRect;
        if (!brushRect) {
            brushRect = displayables.brushRect = new Rect({
                silent: true,
                style: dataZoomModel.getModel('brushStyle').getItemStyle()
            });
            displayables.sliderGroup.add(brushRect);
        }

        brushRect.attr('ignore', false);

        const brushStart = this._brushStart;

        const sliderGroup = this._displayables.sliderGroup;

        const endPoint = sliderGroup.transformCoordToLocal(mouseX, mouseY);
        const startPoint = sliderGroup.transformCoordToLocal(brushStart.x, brushStart.y);

        const size = this._size;

        endPoint[0] = Math.max(Math.min(size[0], endPoint[0]), 0);

        brushRect.setShape({
            x: startPoint[0], y: 0,
            width: endPoint[0] - startPoint[0], height: size[1]
        });
    }

    /**
     * This action will be throttled.
     */
    _dispatchZoomAction(realtime: boolean) {
        const range = this._range;

        this.api.dispatchAction({
            type: 'dataZoom',
            from: this.uid,
            dataZoomId: this.dataZoomModel.id,
            animation: realtime ? REALTIME_ANIMATION_CONFIG : null,
            start: range[0],
            end: range[1]
        });
    }

    private _findCoordRect() {
        // Find the grid coresponding to the first axis referred by dataZoom.
        let rect: RectLike;
        const coordSysInfoList = collectReferCoordSysModelInfo(this.dataZoomModel).infoList;

        if (!rect && coordSysInfoList.length) {
            const coordSys = coordSysInfoList[0].model.coordinateSystem;
            rect = coordSys.getRect && coordSys.getRect();
        }

        if (!rect) {
            const width = this.api.getWidth();
            const height = this.api.getHeight();
            rect = {
                x: width * 0.2,
                y: height * 0.2,
                width: width * 0.6,
                height: height * 0.6
            };
        }

        return rect;
    }

}

function getOtherDim(thisDim: 'x' | 'y' | 'radius' | 'angle' | 'single' | 'z') {
    // FIXME
    // 这个逻辑和getOtherAxis里一致，但是写在这里是否不好
    const map = {x: 'y', y: 'x', radius: 'angle', angle: 'radius'};
    return map[thisDim as 'x' | 'y' | 'radius' | 'angle'];
}

function getCursor(orient: LayoutOrient) {
    return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
}

export default SliderZoomView;
