/*
* 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 * as zrUtil from 'zrender/src/core/util';
import LinearGradient, { LinearGradientObject } from 'zrender/src/graphic/LinearGradient';
import * as eventTool from 'zrender/src/core/event';
import VisualMapView from './VisualMapView';
import * as graphic from '../../util/graphic';
import * as numberUtil from '../../util/number';
import sliderMove from '../helper/sliderMove';
import * as helper from './helper';
import * as modelUtil from '../../util/model';
import VisualMapModel from './VisualMapModel';
import ContinuousModel from './ContinuousModel';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import Element, { ElementEvent } from 'zrender/src/Element';
import { TextVerticalAlign, TextAlign } from 'zrender/src/core/types';
import { ColorString, Payload } from '../../util/types';
import { parsePercent } from 'zrender/src/contain/text';
import { setAsHighDownDispatcher } from '../../util/states';
import { createSymbol } from '../../util/symbol';
import ZRImage from 'zrender/src/graphic/Image';
import { ECData, getECData } from '../../util/innerStore';
import { createTextStyle } from '../../label/labelStyle';
import { findEventDispatcher } from '../../util/event';

const linearMap = numberUtil.linearMap;
const each = zrUtil.each;
const mathMin = Math.min;
const mathMax = Math.max;

// Arbitrary value
const HOVER_LINK_SIZE = 12;
const HOVER_LINK_OUT = 6;

type Orient = VisualMapModel['option']['orient'];

type ShapeStorage = {
    handleThumbs: graphic.Path[]
    handleLabelPoints: number[][]
    handleLabels: graphic.Text[]

    inRange: graphic.Polygon
    outOfRange: graphic.Polygon

    mainGroup: graphic.Group

    indicator: graphic.Path
    indicatorLabel: graphic.Text
    indicatorLabelPoint: number[]
};

type TargetDataIndices = ReturnType<ContinuousModel['findTargetDataIndices']>;

type BarVisual = {
    barColor: LinearGradient,
    barPoints: number[][]
    handlesColor: ColorString[]
};

type Direction = 'left' | 'right' | 'top' | 'bottom';
// Notice:
// Any "interval" should be by the order of [low, high].
// "handle0" (handleIndex === 0) maps to
// low data value: this._dataInterval[0] and has low coord.
// "handle1" (handleIndex === 1) maps to
// high data value: this._dataInterval[1] and has high coord.
// The logic of transform is implemented in this._createBarGroup.

class ContinuousView extends VisualMapView {
    static type = 'visualMap.continuous';
    type = ContinuousView.type;

    visualMapModel: ContinuousModel;

    private _shapes = {} as ShapeStorage;

    private _dataInterval: number[] = [];

    private _handleEnds: number[] = [];

    private _orient: Orient;

    private _useHandle: boolean;

    private _hoverLinkDataIndices: TargetDataIndices = [];

    private _dragging: boolean;

    private _hovering: boolean;

    private _firstShowIndicator: boolean;

    private _api: ExtensionAPI;


    doRender(
        visualMapModel: ContinuousModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: {type: string, from: string}
    ) {
        this._api = api;

        if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
            this._buildView();
        }
    }

    private _buildView() {
        this.group.removeAll();

        const visualMapModel = this.visualMapModel;
        const thisGroup = this.group;

        this._orient = visualMapModel.get('orient');
        this._useHandle = visualMapModel.get('calculable');

        this._resetInterval();

        this._renderBar(thisGroup);

        const dataRangeText = visualMapModel.get('text');
        this._renderEndsText(thisGroup, dataRangeText, 0);
        this._renderEndsText(thisGroup, dataRangeText, 1);

        // Do this for background size calculation.
        this._updateView(true);

        // After updating view, inner shapes is built completely,
        // and then background can be rendered.
        this.renderBackground(thisGroup);

        // Real update view
        this._updateView();

        this._enableHoverLinkToSeries();
        this._enableHoverLinkFromSeries();

        this.positionGroup(thisGroup);
    }

    private _renderEndsText(group: graphic.Group, dataRangeText: string[], endsIndex?: 0 | 1) {
        if (!dataRangeText) {
            return;
        }

        // Compatible with ec2, text[0] map to high value, text[1] map low value.
        let text = dataRangeText[1 - endsIndex];
        text = text != null ? text + '' : '';

        const visualMapModel = this.visualMapModel;
        const textGap = visualMapModel.get('textGap');
        const itemSize = visualMapModel.itemSize;

        const barGroup = this._shapes.mainGroup;
        const position = this._applyTransform(
            [
                itemSize[0] / 2,
                endsIndex === 0 ? -textGap : itemSize[1] + textGap
            ],
            barGroup
        ) as number[];
        const align = this._applyTransform(
            endsIndex === 0 ? 'bottom' : 'top',
            barGroup
        );
        const orient = this._orient;
        const textStyleModel = this.visualMapModel.textStyleModel;

        this.group.add(new graphic.Text({
            style: createTextStyle(textStyleModel, {
                x: position[0],
                y: position[1],
                verticalAlign: orient === 'horizontal' ? 'middle' : align as TextVerticalAlign,
                align: orient === 'horizontal' ? align as TextAlign : 'center',
                text
            })
        }));
    }

    private _renderBar(targetGroup: graphic.Group) {
        const visualMapModel = this.visualMapModel;
        const shapes = this._shapes;
        const itemSize = visualMapModel.itemSize;
        const orient = this._orient;
        const useHandle = this._useHandle;
        const itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize);
        const mainGroup = shapes.mainGroup = this._createBarGroup(itemAlign);

        const gradientBarGroup = new graphic.Group();
        mainGroup.add(gradientBarGroup);

        // Bar
        gradientBarGroup.add(shapes.outOfRange = createPolygon());
        gradientBarGroup.add(shapes.inRange = createPolygon(
            null,
            useHandle ? getCursor(this._orient) : null,
            zrUtil.bind(this._dragHandle, this, 'all', false),
            zrUtil.bind(this._dragHandle, this, 'all', true)
        ));

        // A border radius clip.
        gradientBarGroup.setClipPath(new graphic.Rect({
            shape: {
                x: 0,
                y: 0,
                width: itemSize[0],
                height: itemSize[1],
                r: 3
            }
        }));

        const textRect = visualMapModel.textStyleModel.getTextRect('国');
        const textSize = mathMax(textRect.width, textRect.height);

        // Handle
        if (useHandle) {
            shapes.handleThumbs = [];
            shapes.handleLabels = [];
            shapes.handleLabelPoints = [];

            this._createHandle(visualMapModel, mainGroup, 0, itemSize, textSize, orient);
            this._createHandle(visualMapModel, mainGroup, 1, itemSize, textSize, orient);
        }

        this._createIndicator(visualMapModel, mainGroup, itemSize, textSize, orient);

        targetGroup.add(mainGroup);
    }

    private _createHandle(
        visualMapModel: ContinuousModel,
        mainGroup: graphic.Group,
        handleIndex: 0 | 1,
        itemSize: number[],
        textSize: number,
        orient: Orient
    ) {
        const onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
        const onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
        const handleSize = parsePercent(visualMapModel.get('handleSize'), itemSize[0]);
        const handleThumb = createSymbol(
            visualMapModel.get('handleIcon'),
            -handleSize / 2, -handleSize / 2, handleSize, handleSize,
            null, true
        );
        const cursor = getCursor(this._orient);
        handleThumb.attr({
            cursor: cursor,
            draggable: true,
            drift: onDrift,
            ondragend: onDragEnd,
            onmousemove(e) {
                eventTool.stop(e.event);
            }
        });
        handleThumb.x = itemSize[0] / 2;

        handleThumb.useStyle(visualMapModel.getModel('handleStyle').getItemStyle());
        (handleThumb as graphic.Path).setStyle({
            strokeNoScale: true,
            strokeFirst: true
        });
        (handleThumb as graphic.Path).style.lineWidth *= 2;

        handleThumb.ensureState('emphasis').style = visualMapModel.getModel(['emphasis', 'handleStyle']).getItemStyle();
        setAsHighDownDispatcher(handleThumb, true);

        mainGroup.add(handleThumb);

        // Text is always horizontal layout but should not be effected by
        // transform (orient/inverse). So label is built separately but not
        // use zrender/graphic/helper/RectText, and is located based on view
        // group (according to handleLabelPoint) but not barGroup.
        const textStyleModel = this.visualMapModel.textStyleModel;
        const handleLabel = new graphic.Text({
            cursor: cursor,
            draggable: true,
            drift: onDrift,
            onmousemove(e) {
                // Fot mobile devicem, prevent screen slider on the button.
                eventTool.stop(e.event);
            },
            ondragend: onDragEnd,
            style: createTextStyle(textStyleModel, {
                x: 0,
                y: 0,
                text: ''
            })
        });
        handleLabel.ensureState('blur').style = {
            opacity: 0.1
        };
        handleLabel.stateTransition = { duration: 200 };

        this.group.add(handleLabel);

        const handleLabelPoint = [handleSize, 0];

        const shapes = this._shapes;
        shapes.handleThumbs[handleIndex] = handleThumb;
        shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
        shapes.handleLabels[handleIndex] = handleLabel;
    }

    private _createIndicator(
        visualMapModel: ContinuousModel,
        mainGroup: graphic.Group,
        itemSize: number[],
        textSize: number,
        orient: Orient
    ) {
        const scale = parsePercent(visualMapModel.get('indicatorSize'), itemSize[0]);
        const indicator = createSymbol(
            visualMapModel.get('indicatorIcon'),
            -scale / 2, -scale / 2, scale, scale,
            null, true
        );
        indicator.attr({
            cursor: 'move',
            invisible: true,
            silent: true,
            x: itemSize[0] / 2
        });
        const indicatorStyle = visualMapModel.getModel('indicatorStyle').getItemStyle();
        if (indicator instanceof ZRImage) {
            const pathStyle = indicator.style;
            indicator.useStyle(zrUtil.extend({
                // TODO other properties like x, y ?
                image: pathStyle.image,
                x: pathStyle.x, y: pathStyle.y,
                width: pathStyle.width, height: pathStyle.height
            }, indicatorStyle));
        }
        else {
            indicator.useStyle(indicatorStyle);
        }

        mainGroup.add(indicator);

        const textStyleModel = this.visualMapModel.textStyleModel;
        const indicatorLabel = new graphic.Text({
            silent: true,
            invisible: true,
            style: createTextStyle(textStyleModel, {
                x: 0,
                y: 0,
                text: ''
            })
        });
        this.group.add(indicatorLabel);

        const indicatorLabelPoint = [
            (orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT) + itemSize[0] / 2,
            0
        ];

        const shapes = this._shapes;
        shapes.indicator = indicator;
        shapes.indicatorLabel = indicatorLabel;
        shapes.indicatorLabelPoint = indicatorLabelPoint;

        this._firstShowIndicator = true;
    }

    private _dragHandle(
        handleIndex: 0 | 1 | 'all',
        isEnd?: boolean,
        // dx is event from ondragend if isEnd is true. It's not used
        dx?: number | ElementEvent,
        dy?: number
    ) {
        if (!this._useHandle) {
            return;
        }

        this._dragging = !isEnd;

        if (!isEnd) {
            // Transform dx, dy to bar coordination.
            const vertex = this._applyTransform([dx as number, dy], this._shapes.mainGroup, true) as number[];
            this._updateInterval(handleIndex, vertex[1]);

            this._hideIndicator();
            // Considering realtime, update view should be executed
            // before dispatch action.
            this._updateView();
        }

        // dragEnd do not dispatch action when realtime.
        if (isEnd === !this.visualMapModel.get('realtime')) { // jshint ignore:line
            this.api.dispatchAction({
                type: 'selectDataRange',
                from: this.uid,
                visualMapId: this.visualMapModel.id,
                selected: this._dataInterval.slice()
            });
        }

        if (isEnd) {
            !this._hovering && this._clearHoverLinkToSeries();
        }
        else if (useHoverLinkOnHandle(this.visualMapModel)) {
            this._doHoverLinkToSeries(this._handleEnds[handleIndex as 0 | 1], false);
        }
    }

    private _resetInterval() {
        const visualMapModel = this.visualMapModel;

        const dataInterval = this._dataInterval = visualMapModel.getSelected();
        const dataExtent = visualMapModel.getExtent();
        const sizeExtent = [0, visualMapModel.itemSize[1]];

        this._handleEnds = [
            linearMap(dataInterval[0], dataExtent, sizeExtent, true),
            linearMap(dataInterval[1], dataExtent, sizeExtent, true)
        ];
    }

    /**
     * @private
     * @param {(number|string)} handleIndex 0 or 1 or 'all'
     * @param {number} dx
     * @param {number} dy
     */
    private _updateInterval(handleIndex: 0 | 1 | 'all', delta: number) {
        delta = delta || 0;
        const visualMapModel = this.visualMapModel;
        const handleEnds = this._handleEnds;
        const sizeExtent = [0, visualMapModel.itemSize[1]];

        sliderMove(
            delta,
            handleEnds,
            sizeExtent,
            handleIndex,
            // cross is forbiden
            0
        );

        const dataExtent = visualMapModel.getExtent();
        // Update data interval.
        this._dataInterval = [
            linearMap(handleEnds[0], sizeExtent, dataExtent, true),
            linearMap(handleEnds[1], sizeExtent, dataExtent, true)
        ];
    }

    private _updateView(forSketch?: boolean) {
        const visualMapModel = this.visualMapModel;
        const dataExtent = visualMapModel.getExtent();
        const shapes = this._shapes;

        const outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
        const inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;

        const visualInRange = this._createBarVisual(
            this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'
        );
        const visualOutOfRange = this._createBarVisual(
            dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'
        );

        shapes.inRange
            .setStyle({
                fill: visualInRange.barColor
                // opacity: visualInRange.opacity
            })
            .setShape('points', visualInRange.barPoints);
        shapes.outOfRange
            .setStyle({
                fill: visualOutOfRange.barColor
                // opacity: visualOutOfRange.opacity
            })
            .setShape('points', visualOutOfRange.barPoints);

        this._updateHandle(inRangeHandleEnds, visualInRange);
    }

    private _createBarVisual(
        dataInterval: number[],
        dataExtent: number[],
        handleEnds: number[],
        forceState: ContinuousModel['stateList'][number]
    ): BarVisual {
        const opts = {
            forceState: forceState,
            convertOpacityToAlpha: true
        };
        const colorStops = this._makeColorGradient(dataInterval, opts);

        const symbolSizes = [
            this.getControllerVisual(dataInterval[0], 'symbolSize', opts) as number,
            this.getControllerVisual(dataInterval[1], 'symbolSize', opts) as number
        ];
        const barPoints = this._createBarPoints(handleEnds, symbolSizes);

        return {
            barColor: new LinearGradient(0, 0, 0, 1, colorStops),
            barPoints: barPoints,
            handlesColor: [
                colorStops[0].color,
                colorStops[colorStops.length - 1].color
            ]
        };
    }

    private _makeColorGradient(
        dataInterval: number[],
        opts: {
            forceState?: ContinuousModel['stateList'][number]
            convertOpacityToAlpha?: boolean
        }
    ) {
        // Considering colorHue, which is not linear, so we have to sample
        // to calculate gradient color stops, but not only caculate head
        // and tail.
        const sampleNumber = 100; // Arbitrary value.
        const colorStops: LinearGradientObject['colorStops'] = [];
        const step = (dataInterval[1] - dataInterval[0]) / sampleNumber;

        colorStops.push({
            color: this.getControllerVisual(dataInterval[0], 'color', opts) as ColorString,
            offset: 0
        });

        for (let i = 1; i < sampleNumber; i++) {
            const currValue = dataInterval[0] + step * i;
            if (currValue > dataInterval[1]) {
                break;
            }
            colorStops.push({
                color: this.getControllerVisual(currValue, 'color', opts) as ColorString,
                offset: i / sampleNumber
            });
        }

        colorStops.push({
            color: this.getControllerVisual(dataInterval[1], 'color', opts) as ColorString,
            offset: 1
        });

        return colorStops;
    }

    private _createBarPoints(handleEnds: number[], symbolSizes: number[]) {
        const itemSize = this.visualMapModel.itemSize;

        return [
            [itemSize[0] - symbolSizes[0], handleEnds[0]],
            [itemSize[0], handleEnds[0]],
            [itemSize[0], handleEnds[1]],
            [itemSize[0] - symbolSizes[1], handleEnds[1]]
        ];
    }

    private _createBarGroup(itemAlign: helper.ItemAlign) {
        const orient = this._orient;
        const inverse = this.visualMapModel.get('inverse');

        return new graphic.Group(
            (orient === 'horizontal' && !inverse)
            ? {scaleX: itemAlign === 'bottom' ? 1 : -1, rotation: Math.PI / 2}
            : (orient === 'horizontal' && inverse)
            ? {scaleX: itemAlign === 'bottom' ? -1 : 1, rotation: -Math.PI / 2}
            : (orient === 'vertical' && !inverse)
            ? {scaleX: itemAlign === 'left' ? 1 : -1, scaleY: -1}
            : {scaleX: itemAlign === 'left' ? 1 : -1}
        );
    }

    private _updateHandle(handleEnds: number[], visualInRange: BarVisual) {
        if (!this._useHandle) {
            return;
        }

        const shapes = this._shapes;
        const visualMapModel = this.visualMapModel;
        const handleThumbs = shapes.handleThumbs;
        const handleLabels = shapes.handleLabels;
        const itemSize = visualMapModel.itemSize;
        const dataExtent = visualMapModel.getExtent();

        each([0, 1], function (handleIndex) {
            const handleThumb = handleThumbs[handleIndex];
            handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]);
            handleThumb.y = handleEnds[handleIndex];

            const val = linearMap(handleEnds[handleIndex], [0, itemSize[1]], dataExtent, true);
            const symbolSize = this.getControllerVisual(val, 'symbolSize') as number;

            handleThumb.scaleX = handleThumb.scaleY = symbolSize / itemSize[0];
            handleThumb.x = itemSize[0] - symbolSize / 2;

            // Update handle label position.
            const textPoint = graphic.applyTransform(
                shapes.handleLabelPoints[handleIndex],
                graphic.getTransform(handleThumb, this.group)
            );
            handleLabels[handleIndex].setStyle({
                x: textPoint[0],
                y: textPoint[1],
                text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
                verticalAlign: 'middle',
                align: this._orient === 'vertical' ? this._applyTransform(
                    'left',
                    shapes.mainGroup
                ) as TextAlign : 'center'
            });
        }, this);
    }

    private _showIndicator(
        cursorValue: number,
        textValue: number,
        rangeSymbol?: string,
        halfHoverLinkSize?: number
    ) {
        const visualMapModel = this.visualMapModel;
        const dataExtent = visualMapModel.getExtent();
        const itemSize = visualMapModel.itemSize;
        const sizeExtent = [0, itemSize[1]];

        const shapes = this._shapes;
        const indicator = shapes.indicator;
        if (!indicator) {
            return;
        }

        indicator.attr('invisible', false);

        const opts = {convertOpacityToAlpha: true};
        const color = this.getControllerVisual(cursorValue, 'color', opts) as ColorString;
        const symbolSize = this.getControllerVisual(cursorValue, 'symbolSize') as number;
        const y = linearMap(cursorValue, dataExtent, sizeExtent, true);
        const x = itemSize[0] - symbolSize / 2;

        const oldIndicatorPos = { x: indicator.x, y: indicator.y };
        // Update handle label position.
        indicator.y = y;
        indicator.x = x;
        const textPoint = graphic.applyTransform(
            shapes.indicatorLabelPoint,
            graphic.getTransform(indicator, this.group)
        );

        const indicatorLabel = shapes.indicatorLabel;
        indicatorLabel.attr('invisible', false);
        const align = this._applyTransform('left', shapes.mainGroup);
        const orient = this._orient;
        const isHorizontal = orient === 'horizontal';
        indicatorLabel.setStyle({
            text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
            verticalAlign: isHorizontal ? align as TextVerticalAlign : 'middle',
            align: isHorizontal ? 'center' : align as TextAlign
        });

        const indicatorNewProps = {
            x: x,
            y: y,
            style: {
                fill: color
            }
        };
        const labelNewProps = {
            style: {
                x: textPoint[0],
                y: textPoint[1]
            }
        };

        if (visualMapModel.ecModel.isAnimationEnabled() && !this._firstShowIndicator) {
            const animationCfg = {
                duration: 100,
                easing: 'cubicInOut',
                additive: true
            } as const;
            indicator.x = oldIndicatorPos.x;
            indicator.y = oldIndicatorPos.y;
            indicator.animateTo(indicatorNewProps, animationCfg);
            indicatorLabel.animateTo(labelNewProps, animationCfg);
        }
        else {
            indicator.attr(indicatorNewProps);
            indicatorLabel.attr(labelNewProps);
        }

        this._firstShowIndicator = false;

        const handleLabels = this._shapes.handleLabels;
        if (handleLabels) {
            for (let i = 0; i < handleLabels.length; i++) {
                // Fade out handle labels.
                // NOTE: Must use api enter/leave on emphasis/blur/select state. Or the global states manager will change it.
                this._api.enterBlur(handleLabels[i]);
            }
        }
    }

    private _enableHoverLinkToSeries() {
        const self = this;
        this._shapes.mainGroup

            .on('mousemove', function (e) {
                self._hovering = true;

                if (!self._dragging) {
                    const itemSize = self.visualMapModel.itemSize;
                    const pos = self._applyTransform(
                        [e.offsetX, e.offsetY], self._shapes.mainGroup, true, true
                    );
                    // For hover link show when hover handle, which might be
                    // below or upper than sizeExtent.
                    pos[1] = mathMin(mathMax(0, pos[1]), itemSize[1]);
                    self._doHoverLinkToSeries(
                        pos[1],
                        0 <= pos[0] && pos[0] <= itemSize[0]
                    );
                }
            })

            .on('mouseout', function () {
                // When mouse is out of handle, hoverLink still need
                // to be displayed when realtime is set as false.
                self._hovering = false;
                !self._dragging && self._clearHoverLinkToSeries();
            });
    }

    private _enableHoverLinkFromSeries() {
        const zr = this.api.getZr();

        if (this.visualMapModel.option.hoverLink) {
            zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this);
            zr.on('mouseout', this._hideIndicator, this);
        }
        else {
            this._clearHoverLinkFromSeries();
        }
    }

    private _doHoverLinkToSeries(cursorPos: number, hoverOnBar?: boolean) {
        const visualMapModel = this.visualMapModel;
        const itemSize = visualMapModel.itemSize;

        if (!visualMapModel.option.hoverLink) {
            return;
        }

        const sizeExtent = [0, itemSize[1]];
        const dataExtent = visualMapModel.getExtent();

        // For hover link show when hover handle, which might be below or upper than sizeExtent.
        cursorPos = mathMin(mathMax(sizeExtent[0], cursorPos), sizeExtent[1]);

        const halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent);
        const hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize];
        const cursorValue = linearMap(cursorPos, sizeExtent, dataExtent, true);
        const valueRange = [
            linearMap(hoverRange[0], sizeExtent, dataExtent, true),
            linearMap(hoverRange[1], sizeExtent, dataExtent, true)
        ];
        // Consider data range is out of visualMap range, see test/visualMap-continuous.html,
        // where china and india has very large population.
        hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity);
        hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity);

        // Do not show indicator when mouse is over handle,
        // otherwise labels overlap, especially when dragging.
        if (hoverOnBar) {
            if (valueRange[0] === -Infinity) {
                this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize);
            }
            else if (valueRange[1] === Infinity) {
                this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize);
            }
            else {
                this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize);
            }
        }

        // When realtime is set as false, handles, which are in barGroup,
        // also trigger hoverLink, which help user to realize where they
        // focus on when dragging. (see test/heatmap-large.html)
        // When realtime is set as true, highlight will not show when hover
        // handle, because the label on handle, which displays a exact value
        // but not range, might mislead users.
        const oldBatch = this._hoverLinkDataIndices;
        let newBatch: TargetDataIndices = [];
        if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
            newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
        }

        const resultBatches = modelUtil.compressBatches(oldBatch, newBatch);

        this._dispatchHighDown('downplay', helper.makeHighDownBatch(resultBatches[0], visualMapModel));
        this._dispatchHighDown('highlight', helper.makeHighDownBatch(resultBatches[1], visualMapModel));
    }

    private _hoverLinkFromSeriesMouseOver(e: ElementEvent) {
        let ecData: ECData;

        findEventDispatcher(e.target, target => {
            const currECData = getECData(target);
            if (currECData.dataIndex != null) {
                ecData = currECData;
                return true;
            }
        }, true);

        if (!ecData) {
            return;
        }

        const dataModel = this.ecModel.getSeriesByIndex(ecData.seriesIndex);

        const visualMapModel = this.visualMapModel;
        if (!visualMapModel.isTargetSeries(dataModel)) {
            return;
        }

        const data = dataModel.getData(ecData.dataType);
        const value = data.getStore().get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex) as number;

        if (!isNaN(value)) {
            this._showIndicator(value, value);
        }
    }

    private _hideIndicator() {
        const shapes = this._shapes;
        shapes.indicator && shapes.indicator.attr('invisible', true);
        shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);

        const handleLabels = this._shapes.handleLabels;
        if (handleLabels) {
            for (let i = 0; i < handleLabels.length; i++) {
                // Fade out handle labels.
                // NOTE: Must use api enter/leave on emphasis/blur/select state. Or the global states manager will change it.
                this._api.leaveBlur(handleLabels[i]);
            }
        }
    }

    private _clearHoverLinkToSeries() {
        this._hideIndicator();

        const indices = this._hoverLinkDataIndices;
        this._dispatchHighDown('downplay', helper.makeHighDownBatch(indices, this.visualMapModel));

        indices.length = 0;
    }

    private _clearHoverLinkFromSeries() {
        this._hideIndicator();

        const zr = this.api.getZr();
        zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
        zr.off('mouseout', this._hideIndicator);
    }
    private _applyTransform(vertex: number[], element: Element, inverse?: boolean, global?: boolean): number[]
    private _applyTransform(vertex: Direction, element: Element, inverse?: boolean, global?: boolean): Direction
    private _applyTransform(
        vertex: number[] | Direction,
        element: Element,
        inverse?: boolean,
        global?: boolean
    ) {
        const transform = graphic.getTransform(element, global ? null : this.group);

        return zrUtil.isArray(vertex)
            ? graphic.applyTransform(vertex, transform, inverse)
            : graphic.transformDirection(vertex, transform, inverse);
    }

 // TODO: TYPE more specified payload types.
    private _dispatchHighDown(type: 'highlight' | 'downplay', batch: Payload['batch']) {
        batch && batch.length && this.api.dispatchAction({
            type: type,
            batch: batch
        });
    }

    /**
     * @override
     */
    dispose() {
        this._clearHoverLinkFromSeries();
        this._clearHoverLinkToSeries();
    }

    /**
     * @override
     */
    remove() {
        this._clearHoverLinkFromSeries();
        this._clearHoverLinkToSeries();
    }

}

function createPolygon(
    points?: number[][],
    cursor?: string,
    onDrift?: (x: number, y: number) => void,
    onDragEnd?: () => void
) {
    return new graphic.Polygon({
        shape: {points: points},
        draggable: !!onDrift,
        cursor: cursor,
        drift: onDrift,
        onmousemove(e) {
            // Fot mobile devicem, prevent screen slider on the button.
            eventTool.stop(e.event);
        },
        ondragend: onDragEnd
    });
}

function getHalfHoverLinkSize(visualMapModel: ContinuousModel, dataExtent: number[], sizeExtent: number[]) {
    let halfHoverLinkSize = HOVER_LINK_SIZE / 2;
    const hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');
    if (hoverLinkDataSize) {
        halfHoverLinkSize = linearMap(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2;
    }
    return halfHoverLinkSize;
}

function useHoverLinkOnHandle(visualMapModel: ContinuousModel) {
    const hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle');
    return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle);
}

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

export default ContinuousView;
