/*
* 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, clone, trim, isString, isFunction, isArray, isObject, extend } from 'zrender/src/core/util';
import env from 'zrender/src/core/env';
import TooltipHTMLContent from './TooltipHTMLContent';
import TooltipRichContent from './TooltipRichContent';
import { convertToColorString, formatTpl, TooltipMarker } from '../../util/format';
import { parsePercent } from '../../util/number';
import { Rect } from '../../util/graphic';
import findPointFromSeries from '../axisPointer/findPointFromSeries';
import { getLayoutRect } from '../../util/layout';
import Model from '../../model/Model';
import * as globalListener from '../axisPointer/globalListener';
import * as axisHelper from '../../coord/axisHelper';
import * as axisPointerViewHelper from '../axisPointer/viewHelper';
import { getTooltipRenderMode, preParseFinder, queryReferringComponents } from '../../util/model';
import ComponentView from '../../view/Component';
import { format as timeFormat } from '../../util/time';
import {
    HorizontalAlign,
    VerticalAlign,
    ZRRectLike,
    BoxLayoutOptionMixin,
    CallbackDataParams,
    TooltipRenderMode,
    ECElement,
    CommonTooltipOption,
    ZRColor,
    ComponentMainType,
    ComponentItemTooltipOption
} from '../../util/types';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import TooltipModel, { TooltipOption } from './TooltipModel';
import Element from 'zrender/src/Element';
import { AxisBaseModel } from '../../coord/AxisBaseModel';
import { ECData, getECData } from '../../util/innerStore';
import { shouldTooltipConfine } from './helper';
import { DataByCoordSys, DataByAxis } from '../axisPointer/axisTrigger';
import { normalizeTooltipFormatResult } from '../../model/mixin/dataFormat';
import { createTooltipMarkup, buildTooltipMarkup, TooltipMarkupStyleCreator } from './tooltipMarkup';
import { findEventDispatcher } from '../../util/event';
import { clear, createOrUpdate } from '../../util/throttle';

const proxyRect = new Rect({
    shape: { x: -1, y: -1, width: 2, height: 2 }
});

interface DataIndex {
    seriesIndex: number
    dataIndex: number

    dataIndexInside: number
}

interface ShowTipPayload {
    type?: 'showTip'
    from?: string

    // Type 1
    tooltip?: ECData['tooltipConfig']['option']

    // Type 2
    dataByCoordSys?: DataByCoordSys[]
    tooltipOption?: CommonTooltipOption<TooltipCallbackDataParams | TooltipCallbackDataParams[]>

    // Type 3
    seriesIndex?: number
    dataIndex?: number

    // Type 4
    name?: string // target item name that enable tooltip.
    // legendIndex: 0,
    // toolboxId: 'some_id',
    // geoName: 'some_name',

    x?: number
    y?: number
    position?: TooltipOption['position']

    dispatchAction?: ExtensionAPI['dispatchAction']
}

interface HideTipPayload {
    type?: 'hideTip'
    from?: string

    dispatchAction?: ExtensionAPI['dispatchAction']
}

interface TryShowParams {
    target?: ECElement,

    offsetX?: number
    offsetY?: number

    /**
     * Used for axis trigger.
     */
    dataByCoordSys?: DataByCoordSys[]

    tooltipOption?: ComponentItemTooltipOption<TooltipCallbackDataParams | TooltipCallbackDataParams[]>

    position?: TooltipOption['position']
    /**
     * If `position` is not set in payload nor option, use it.
     */
    positionDefault?: TooltipOption['position']
}

type TooltipCallbackDataParams = CallbackDataParams & {
    axisDim?: string
    axisIndex?: number
    axisType?: string
    axisId?: string
    // TODO: TYPE Value type
    axisValue?: string | number
    axisValueLabel?: string
    marker?: TooltipMarker
};

class TooltipView extends ComponentView {
    static type = 'tooltip' as const;
    type = TooltipView.type;

    private _renderMode: TooltipRenderMode;

    private _tooltipModel: TooltipModel;

    private _ecModel: GlobalModel;

    private _api: ExtensionAPI;

    private _alwaysShowContent: boolean;

    private _tooltipContent: TooltipHTMLContent | TooltipRichContent;

    private _refreshUpdateTimeout: number;

    private _lastX: number;
    private _lastY: number;

    private _ticket: string;

    private _showTimout: number;

    private _lastDataByCoordSys: DataByCoordSys[];
    private _cbParamsList: TooltipCallbackDataParams[];

    init(ecModel: GlobalModel, api: ExtensionAPI) {
        if (env.node || !api.getDom()) {
            return;
        }

        const tooltipModel = ecModel.getComponent('tooltip') as TooltipModel;
        const renderMode = this._renderMode = getTooltipRenderMode(tooltipModel.get('renderMode'));

        this._tooltipContent = renderMode === 'richText'
            ? new TooltipRichContent(api)
            : new TooltipHTMLContent(api.getDom(), api, {
                appendToBody: tooltipModel.get('appendToBody', true)
            });
    }

    render(
        tooltipModel: TooltipModel,
        ecModel: GlobalModel,
        api: ExtensionAPI
    ) {
        if (env.node || !api.getDom()) {
            return;
        }

        // Reset
        this.group.removeAll();

        this._tooltipModel = tooltipModel;

        this._ecModel = ecModel;

        this._api = api;

        /**
         * @private
         * @type {boolean}
         */
        this._alwaysShowContent = tooltipModel.get('alwaysShowContent');

        const tooltipContent = this._tooltipContent;
        tooltipContent.update(tooltipModel);
        tooltipContent.setEnterable(tooltipModel.get('enterable'));

        this._initGlobalListener();

        this._keepShow();

        // PENDING
        // `mousemove` event will be triggered very frequently when the mouse moves fast,
        // which causes that the `updatePosition` function was also called frequently.
        // In Chrome with devtools open and Firefox, tooltip looks laggy and shakes. See #14695 #16101
        // To avoid frequent triggering,
        // consider throttling it in 50ms when transition is enabled
        if (this._renderMode !== 'richText' && tooltipModel.get('transitionDuration')) {
            createOrUpdate(this, '_updatePosition', 50, 'fixRate');
        }
        else {
            clear(this, '_updatePosition');
        }
    }

    private _initGlobalListener() {
        const tooltipModel = this._tooltipModel;
        const triggerOn = tooltipModel.get('triggerOn');

        globalListener.register(
            'itemTooltip',
            this._api,
            bind(function (currTrigger, e, dispatchAction) {
                // If 'none', it is not controlled by mouse totally.
                if (triggerOn !== 'none') {
                    if (triggerOn.indexOf(currTrigger) >= 0) {
                        this._tryShow(e, dispatchAction);
                    }
                    else if (currTrigger === 'leave') {
                        this._hide(dispatchAction);
                    }
                }
            }, this)
        );
    }

    private _keepShow() {
        const tooltipModel = this._tooltipModel;
        const ecModel = this._ecModel;
        const api = this._api;
        const triggerOn = tooltipModel.get('triggerOn');

        // Try to keep the tooltip show when refreshing
        if (this._lastX != null
            && this._lastY != null
            // When user is willing to control tooltip totally using API,
            // self.manuallyShowTip({x, y}) might cause tooltip hide,
            // which is not expected.
            && triggerOn !== 'none'
            && triggerOn !== 'click'
        ) {
            const self = this;
            clearTimeout(this._refreshUpdateTimeout);
            this._refreshUpdateTimeout = setTimeout(function () {
                // Show tip next tick after other charts are rendered
                // In case highlight action has wrong result
                // FIXME
                !api.isDisposed() && self.manuallyShowTip(tooltipModel, ecModel, api, {
                    x: self._lastX,
                    y: self._lastY,
                    dataByCoordSys: self._lastDataByCoordSys
                });
            }) as any;
        }
    }

    /**
     * Show tip manually by
     * dispatchAction({
     *     type: 'showTip',
     *     x: 10,
     *     y: 10
     * });
     * Or
     * dispatchAction({
     *      type: 'showTip',
     *      seriesIndex: 0,
     *      dataIndex or dataIndexInside or name
     * });
     *
     *  TODO Batch
     */
    manuallyShowTip(
        tooltipModel: TooltipModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: ShowTipPayload
    ) {
        if (payload.from === this.uid || env.node || !api.getDom()) {
            return;
        }

        const dispatchAction = makeDispatchAction(payload, api);

        // Reset ticket
        this._ticket = '';

        // When triggered from axisPointer.
        const dataByCoordSys = payload.dataByCoordSys;

        const cmptRef = findComponentReference(payload, ecModel, api);

        if (cmptRef) {
            const rect = cmptRef.el.getBoundingRect().clone();
            rect.applyTransform(cmptRef.el.transform);
            this._tryShow({
                offsetX: rect.x + rect.width / 2,
                offsetY: rect.y + rect.height / 2,
                target: cmptRef.el,
                position: payload.position,
                // When manully trigger, the mouse is not on the el, so we'd better to
                // position tooltip on the bottom of the el and display arrow is possible.
                positionDefault: 'bottom'
            }, dispatchAction);
        }
        else if (payload.tooltip && payload.x != null && payload.y != null) {
            const el = proxyRect as unknown as ECElement;
            el.x = payload.x;
            el.y = payload.y;
            el.update();
            getECData(el).tooltipConfig = {
                name: null,
                option: payload.tooltip
            };
            // Manually show tooltip while view is not using zrender elements.
            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                target: el
            }, dispatchAction);
        }
        else if (dataByCoordSys) {
            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                position: payload.position,
                dataByCoordSys: dataByCoordSys,
                tooltipOption: payload.tooltipOption
            }, dispatchAction);
        }
        else if (payload.seriesIndex != null) {

            if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) {
                return;
            }

            const pointInfo = findPointFromSeries(payload, ecModel);
            const cx = pointInfo.point[0];
            const cy = pointInfo.point[1];
            if (cx != null && cy != null) {
                this._tryShow({
                    offsetX: cx,
                    offsetY: cy,
                    target: pointInfo.el,
                    position: payload.position,
                    // When manully trigger, the mouse is not on the el, so we'd better to
                    // position tooltip on the bottom of the el and display arrow is possible.
                    positionDefault: 'bottom'
                }, dispatchAction);
            }
        }
        else if (payload.x != null && payload.y != null) {
            // FIXME
            // should wrap dispatchAction like `axisPointer/globalListener` ?
            api.dispatchAction({
                type: 'updateAxisPointer',
                x: payload.x,
                y: payload.y
            });

            this._tryShow({
                offsetX: payload.x,
                offsetY: payload.y,
                position: payload.position,
                target: api.getZr().findHover(payload.x, payload.y).target
            }, dispatchAction);
        }
    }

    manuallyHideTip(
        tooltipModel: TooltipModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: HideTipPayload
    ) {
        const tooltipContent = this._tooltipContent;

        if (!this._alwaysShowContent && this._tooltipModel) {
            tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));
        }

        this._lastX = this._lastY = this._lastDataByCoordSys = null;

        if (payload.from !== this.uid) {
            this._hide(makeDispatchAction(payload, api));
        }
    }

    // Be compatible with previous design, that is, when tooltip.type is 'axis' and
    // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer
    // and tooltip.
    private _manuallyAxisShowTip(
        tooltipModel: TooltipModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: ShowTipPayload
    ) {
        const seriesIndex = payload.seriesIndex;
        const dataIndex = payload.dataIndex;
        // @ts-ignore
        const coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;

        if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) {
            return;
        }

        const seriesModel = ecModel.getSeriesByIndex(seriesIndex);
        if (!seriesModel) {
            return;
        }

        const data = seriesModel.getData();
        const tooltipCascadedModel = buildTooltipModel([
            data.getItemModel<TooltipableOption>(dataIndex),
            seriesModel as Model<TooltipableOption>,
            (seriesModel.coordinateSystem || {}).model as Model<TooltipableOption>
        ], this._tooltipModel);

        if (tooltipCascadedModel.get('trigger') !== 'axis') {
            return;
        }

        api.dispatchAction({
            type: 'updateAxisPointer',
            seriesIndex: seriesIndex,
            dataIndex: dataIndex,
            position: payload.position
        });

        return true;
    }

    private _tryShow(
        e: TryShowParams,
        dispatchAction: ExtensionAPI['dispatchAction']
    ) {
        const el = e.target;
        const tooltipModel = this._tooltipModel;

        if (!tooltipModel) {
            return;
        }

        // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed
        this._lastX = e.offsetX;
        this._lastY = e.offsetY;

        const dataByCoordSys = e.dataByCoordSys;
        if (dataByCoordSys && dataByCoordSys.length) {
            this._showAxisTooltip(dataByCoordSys, e);
        }
        else if (el) {
            this._lastDataByCoordSys = null;

            let seriesDispatcher: Element;
            let cmptDispatcher: Element;
            findEventDispatcher(el, (target) => {
                // Always show item tooltip if mouse is on the element with dataIndex
                if (getECData(target).dataIndex != null) {
                    seriesDispatcher = target;
                    return true;
                }
                // Tooltip provided directly. Like legend.
                if (getECData(target).tooltipConfig != null) {
                    cmptDispatcher = target;
                    return true;
                }
            }, true);

            if (seriesDispatcher) {
                this._showSeriesItemTooltip(e, seriesDispatcher, dispatchAction);
            }
            else if (cmptDispatcher) {
                this._showComponentItemTooltip(e, cmptDispatcher, dispatchAction);
            }
            else {
                this._hide(dispatchAction);
            }
        }
        else {
            this._lastDataByCoordSys = null;
            this._hide(dispatchAction);
        }
    }

    private _showOrMove(
        tooltipModel: Model<TooltipOption>,
        cb: () => void
    ) {
        // showDelay is used in this case: tooltip.enterable is set
        // as true. User intent to move mouse into tooltip and click
        // something. `showDelay` makes it easier to enter the content
        // but tooltip do not move immediately.
        const delay = tooltipModel.get('showDelay');
        cb = bind(cb, this);
        clearTimeout(this._showTimout);
        delay > 0
            ? (this._showTimout = setTimeout(cb, delay) as any)
            : cb();
    }

    private _showAxisTooltip(
        dataByCoordSys: DataByCoordSys[],
        e: TryShowParams
    ) {
        const ecModel = this._ecModel;
        const globalTooltipModel = this._tooltipModel;
        const point = [e.offsetX, e.offsetY];
        const singleTooltipModel = buildTooltipModel(
            [e.tooltipOption],
            globalTooltipModel
        );
        const renderMode = this._renderMode;
        const cbParamsList: TooltipCallbackDataParams[] = [];
        const articleMarkup = createTooltipMarkup('section', {
            blocks: [],
            noHeader: true
        });
        // Only for legacy: `Serise['formatTooltip']` returns a string.
        const markupTextArrLegacy: string[] = [];
        const markupStyleCreator = new TooltipMarkupStyleCreator();

        each(dataByCoordSys, function (itemCoordSys) {
            each(itemCoordSys.dataByAxis, function (axisItem) {
                const axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex) as AxisBaseModel;
                const axisValue = axisItem.value;
                if (!axisModel || axisValue == null) {
                    return;
                }
                const axisValueLabel = axisPointerViewHelper.getValueLabel(
                    axisValue, axisModel.axis, ecModel,
                    axisItem.seriesDataIndices,
                    axisItem.valueLabelOpt
                );
                const axisSectionMarkup = createTooltipMarkup('section', {
                    header: axisValueLabel,
                    noHeader: !trim(axisValueLabel),
                    sortBlocks: true,
                    blocks: []
                });
                articleMarkup.blocks.push(axisSectionMarkup);

                each(axisItem.seriesDataIndices, function (idxItem) {
                    const series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
                    const dataIndex = idxItem.dataIndexInside;
                    const cbParams = series.getDataParams(dataIndex) as TooltipCallbackDataParams;
                    // Can't find data.
                    if (cbParams.dataIndex < 0) {
                        return;
                    }

                    cbParams.axisDim = axisItem.axisDim;
                    cbParams.axisIndex = axisItem.axisIndex;
                    cbParams.axisType = axisItem.axisType;
                    cbParams.axisId = axisItem.axisId;
                    cbParams.axisValue = axisHelper.getAxisRawValue(
                        axisModel.axis, { value: axisValue as number }
                    );
                    cbParams.axisValueLabel = axisValueLabel;
                    // Pre-create marker style for makers. Users can assemble richText
                    // text in `formatter` callback and use those markers style.
                    cbParams.marker = markupStyleCreator.makeTooltipMarker(
                        'item', convertToColorString(cbParams.color), renderMode
                    );

                    const seriesTooltipResult = normalizeTooltipFormatResult(
                        series.formatTooltip(dataIndex, true, null)
                    );
                    const frag = seriesTooltipResult.frag;
                    if (frag) {
                        const valueFormatter = buildTooltipModel(
                            [series as Model<TooltipableOption>],
                            globalTooltipModel
                        ).get('valueFormatter');
                        axisSectionMarkup.blocks.push(valueFormatter ? extend({ valueFormatter }, frag) : frag);
                    }
                    if (seriesTooltipResult.text) {
                        markupTextArrLegacy.push(seriesTooltipResult.text);
                    }
                    cbParamsList.push(cbParams);
                });
            });
        });

        // In most cases, the second axis is displays upper on the first one.
        // So we reverse it to look better.
        articleMarkup.blocks.reverse();
        markupTextArrLegacy.reverse();

        const positionExpr = e.position;
        const orderMode = singleTooltipModel.get('order');

        const builtMarkupText = buildTooltipMarkup(
            articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'),
            singleTooltipModel.get('textStyle')
        );
        builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText);
        const blockBreak = renderMode === 'richText' ? '\n\n' : '<br/>';
        const allMarkupText = markupTextArrLegacy.join(blockBreak);

        this._showOrMove(singleTooltipModel, function (this: TooltipView) {
            if (this._updateContentNotChangedOnAxis(dataByCoordSys, cbParamsList)) {
                this._updatePosition(
                    singleTooltipModel,
                    positionExpr,
                    point[0], point[1],
                    this._tooltipContent,
                    cbParamsList
                );
            }
            else {
                this._showTooltipContent(
                    singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '',
                    point[0], point[1], positionExpr, null, markupStyleCreator
                );
            }
        });

        // Do not trigger events here, because this branch only be entered
        // from dispatchAction.
    }

    private _showSeriesItemTooltip(
        e: TryShowParams,
        dispatcher: ECElement,
        dispatchAction: ExtensionAPI['dispatchAction']
    ) {
        const ecModel = this._ecModel;
        const ecData = getECData(dispatcher);
        // Use dataModel in element if possible
        // Used when mouseover on a element like markPoint or edge
        // In which case, the data is not main data in series.
        const seriesIndex = ecData.seriesIndex;
        const seriesModel = ecModel.getSeriesByIndex(seriesIndex);

        // For example, graph link.
        const dataModel = ecData.dataModel || seriesModel;
        const dataIndex = ecData.dataIndex;
        const dataType = ecData.dataType;
        const data = dataModel.getData(dataType);
        const renderMode = this._renderMode;

        const positionDefault = e.positionDefault;
        const tooltipModel = buildTooltipModel(
            [
                data.getItemModel<TooltipableOption>(dataIndex),
                dataModel,
                seriesModel && (seriesModel.coordinateSystem || {}).model as Model<TooltipableOption>
            ],
            this._tooltipModel,
            positionDefault ? { position: positionDefault } : null
        );

        const tooltipTrigger = tooltipModel.get('trigger');
        if (tooltipTrigger != null && tooltipTrigger !== 'item') {
            return;
        }

        const params = dataModel.getDataParams(dataIndex, dataType);
        const markupStyleCreator = new TooltipMarkupStyleCreator();
        // Pre-create marker style for makers. Users can assemble richText
        // text in `formatter` callback and use those markers style.
        params.marker = markupStyleCreator.makeTooltipMarker(
            'item', convertToColorString(params.color), renderMode
        );

        const seriesTooltipResult = normalizeTooltipFormatResult(
            dataModel.formatTooltip(dataIndex, false, dataType)
        );
        const orderMode = tooltipModel.get('order');
        const valueFormatter = tooltipModel.get('valueFormatter');
        const frag = seriesTooltipResult.frag;
        const markupText = frag ? buildTooltipMarkup(
                valueFormatter ? extend({ valueFormatter }, frag) : frag,
                markupStyleCreator,
                renderMode,
                orderMode,
                ecModel.get('useUTC'),
                tooltipModel.get('textStyle')
            )
            : seriesTooltipResult.text;

        const asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;

        this._showOrMove(tooltipModel, function (this: TooltipView) {
            this._showTooltipContent(
                tooltipModel, markupText, params, asyncTicket,
                e.offsetX, e.offsetY, e.position, e.target,
                markupStyleCreator
            );
        });

        // FIXME
        // duplicated showtip if manuallyShowTip is called from dispatchAction.
        dispatchAction({
            type: 'showTip',
            dataIndexInside: dataIndex,
            dataIndex: data.getRawIndex(dataIndex),
            seriesIndex: seriesIndex,
            from: this.uid
        });
    }

    private _showComponentItemTooltip(
        e: TryShowParams,
        el: ECElement,
        dispatchAction: ExtensionAPI['dispatchAction']
    ) {
        const ecData = getECData(el);
        const tooltipConfig = ecData.tooltipConfig;
        let tooltipOpt = tooltipConfig.option || {};
        if (isString(tooltipOpt)) {
            const content = tooltipOpt;
            tooltipOpt = {
                content: content,
                // Fixed formatter
                formatter: content
            };
        }

        const tooltipModelCascade = [tooltipOpt] as TooltipModelOptionCascade[];
        const cmpt = this._ecModel.getComponent(ecData.componentMainType, ecData.componentIndex);
        if (cmpt) {
            tooltipModelCascade.push(cmpt as Model<TooltipableOption>);
        }
        // In most cases, component tooltip formatter has different params with series tooltip formatter,
        // so that they can not share the same formatter. Since the global tooltip formatter is used for series
        // by convension, we do not use it as the default formatter for component.
        tooltipModelCascade.push({ formatter: tooltipOpt.content });

        const positionDefault = e.positionDefault;
        const subTooltipModel = buildTooltipModel(
            tooltipModelCascade,
            this._tooltipModel,
            positionDefault ? { position: positionDefault } : null
        );

        const defaultHtml = subTooltipModel.get('content');
        const asyncTicket = Math.random() + '';
        // PENDING: this case do not support richText style yet.
        const markupStyleCreator = new TooltipMarkupStyleCreator();

        // Do not check whether `trigger` is 'none' here, because `trigger`
        // only works on coordinate system. In fact, we have not found case
        // that requires setting `trigger` nothing on component yet.

        this._showOrMove(subTooltipModel, function (this: TooltipView) {
            // Use formatterParams from element defined in component
            // Avoid users modify it.
            const formatterParams = clone(subTooltipModel.get('formatterParams') as any || {});
            this._showTooltipContent(
                subTooltipModel, defaultHtml, formatterParams,
                asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator
            );
        });

        // If not dispatch showTip, tip may be hide triggered by axis.
        dispatchAction({
            type: 'showTip',
            from: this.uid
        });
    }

    private _showTooltipContent(
        // Use Model<TooltipOption> insteadof TooltipModel because this model may be from series or other options.
        // Instead of top level tooltip.
        tooltipModel: Model<TooltipOption>,
        defaultHtml: string,
        params: TooltipCallbackDataParams | TooltipCallbackDataParams[],
        asyncTicket: string,
        x: number,
        y: number,
        positionExpr: TooltipOption['position'],
        el: ECElement,
        markupStyleCreator: TooltipMarkupStyleCreator
    ) {
        // Reset ticket
        this._ticket = '';

        if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) {
            return;
        }

        const tooltipContent = this._tooltipContent;
        tooltipContent.setEnterable(tooltipModel.get('enterable'));

        const formatter = tooltipModel.get('formatter');
        positionExpr = positionExpr || tooltipModel.get('position');
        let html: string | HTMLElement | HTMLElement[] = defaultHtml;
        const nearPoint = this._getNearestPoint(
            [x, y],
            params,
            tooltipModel.get('trigger'),
            tooltipModel.get('borderColor')
        );
        const nearPointColor = nearPoint.color;

        if (formatter) {
            if (isString(formatter)) {
                const useUTC = tooltipModel.ecModel.get('useUTC');
                const params0 = isArray(params) ? params[0] : params;
                const isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0;
                html = formatter;
                if (isTimeAxis) {
                    html = timeFormat(params0.axisValue, html, useUTC);
                }
                html = formatTpl(html, params, true);
            }
            else if (isFunction(formatter)) {
                const callback = bind(function (cbTicket: string, html: string | HTMLElement | HTMLElement[]) {
                    if (cbTicket === this._ticket) {
                        tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);
                        this._updatePosition(
                            tooltipModel, positionExpr, x, y, tooltipContent, params, el
                        );
                    }
                }, this);
                this._ticket = asyncTicket;
                html = formatter(params, asyncTicket, callback);
            }
            else {
                html = formatter;
            }
        }

        tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr);
        tooltipContent.show(tooltipModel, nearPointColor);
        this._updatePosition(
            tooltipModel, positionExpr, x, y, tooltipContent, params, el
        );

    }

    private _getNearestPoint(
        point: number[],
        tooltipDataParams: TooltipCallbackDataParams | TooltipCallbackDataParams[],
        trigger: TooltipOption['trigger'],
        borderColor: ZRColor
    ): {
        color: ZRColor;
    } {
        if (trigger === 'axis' || isArray(tooltipDataParams)) {
            return {
                color: borderColor || (this._renderMode === 'html' ? '#fff' : 'none')
            };
        }

        if (!isArray(tooltipDataParams)) {
            return {
                color: borderColor || tooltipDataParams.color || tooltipDataParams.borderColor
            };
        }
    }

    _updatePosition(
        tooltipModel: Model<TooltipOption>,
        positionExpr: TooltipOption['position'],
        x: number,  // Mouse x
        y: number,  // Mouse y
        content: TooltipHTMLContent | TooltipRichContent,
        params: TooltipCallbackDataParams | TooltipCallbackDataParams[],
        el?: Element
    ) {
        const viewWidth = this._api.getWidth();
        const viewHeight = this._api.getHeight();

        positionExpr = positionExpr || tooltipModel.get('position');

        const contentSize = content.getSize();
        let align = tooltipModel.get('align');
        let vAlign = tooltipModel.get('verticalAlign');
        const rect = el && el.getBoundingRect().clone();
        el && rect.applyTransform(el.transform);

        if (isFunction(positionExpr)) {
            // Callback of position can be an array or a string specify the position
            positionExpr = positionExpr([x, y], params, content.el, rect, {
                viewSize: [viewWidth, viewHeight],
                contentSize: contentSize.slice() as [number, number]
            });
        }

        if (isArray(positionExpr)) {
            x = parsePercent(positionExpr[0], viewWidth);
            y = parsePercent(positionExpr[1], viewHeight);
        }
        else if (isObject(positionExpr)) {
            const boxLayoutPosition = positionExpr as BoxLayoutOptionMixin;
            boxLayoutPosition.width = contentSize[0];
            boxLayoutPosition.height = contentSize[1];
            const layoutRect = getLayoutRect(
                boxLayoutPosition, { width: viewWidth, height: viewHeight }
            );
            x = layoutRect.x;
            y = layoutRect.y;
            align = null;
            // When positionExpr is left/top/right/bottom,
            // align and verticalAlign will not work.
            vAlign = null;
        }
        // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element
        else if (isString(positionExpr) && el) {
            const pos = calcTooltipPosition(
                positionExpr, rect, contentSize, tooltipModel.get('borderWidth')
            );
            x = pos[0];
            y = pos[1];
        }
        else {
            const pos = refixTooltipPosition(
                x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20
            );
            x = pos[0];
            y = pos[1];
        }

        align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0);
        vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0);

        if (shouldTooltipConfine(tooltipModel)) {
            const pos = confineTooltipPosition(
                x, y, content, viewWidth, viewHeight
            );
            x = pos[0];
            y = pos[1];
        }

        content.moveTo(x, y);
    }

    // FIXME
    // Should we remove this but leave this to user?
    private _updateContentNotChangedOnAxis(
        dataByCoordSys: DataByCoordSys[],
        cbParamsList: TooltipCallbackDataParams[]
    ) {
        const lastCoordSys = this._lastDataByCoordSys;
        const lastCbParamsList = this._cbParamsList;
        let contentNotChanged = !!lastCoordSys
            && lastCoordSys.length === dataByCoordSys.length;

        contentNotChanged && each(lastCoordSys, (lastItemCoordSys, indexCoordSys) => {
            const lastDataByAxis = lastItemCoordSys.dataByAxis || [] as DataByAxis[];
            const thisItemCoordSys = dataByCoordSys[indexCoordSys] || {} as DataByCoordSys;
            const thisDataByAxis = thisItemCoordSys.dataByAxis || [] as DataByAxis[];
            contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length;

            contentNotChanged && each(lastDataByAxis, (lastItem, indexAxis) => {
                const thisItem = thisDataByAxis[indexAxis] || {} as DataByAxis;
                const lastIndices = lastItem.seriesDataIndices || [] as DataIndex[];
                const newIndices = thisItem.seriesDataIndices || [] as DataIndex[];

                contentNotChanged = contentNotChanged
                    && lastItem.value === thisItem.value
                    && lastItem.axisType === thisItem.axisType
                    && lastItem.axisId === thisItem.axisId
                    && lastIndices.length === newIndices.length;

                contentNotChanged && each(lastIndices, (lastIdxItem, j) => {
                    const newIdxItem = newIndices[j];
                    contentNotChanged = contentNotChanged
                        && lastIdxItem.seriesIndex === newIdxItem.seriesIndex
                        && lastIdxItem.dataIndex === newIdxItem.dataIndex;
                });

                // check is cbParams data value changed
                lastCbParamsList && each(lastItem.seriesDataIndices, (idxItem) => {
                    const seriesIdx = idxItem.seriesIndex;
                    const cbParams = cbParamsList[seriesIdx];
                    const lastCbParams = lastCbParamsList[seriesIdx];
                    if (cbParams && lastCbParams && lastCbParams.data !== cbParams.data) {
                        contentNotChanged = false;
                    }
                });
            });
        });

        this._lastDataByCoordSys = dataByCoordSys;
        this._cbParamsList = cbParamsList;

        return !!contentNotChanged;
    }

    private _hide(dispatchAction: ExtensionAPI['dispatchAction']) {
        // Do not directly hideLater here, because this behavior may be prevented
        // in dispatchAction when showTip is dispatched.

        // FIXME
        // duplicated hideTip if manuallyHideTip is called from dispatchAction.
        this._lastDataByCoordSys = null;
        dispatchAction({
            type: 'hideTip',
            from: this.uid
        });
    }

    dispose(ecModel: GlobalModel, api: ExtensionAPI) {
        if (env.node || !api.getDom()) {
            return;
        }
        clear(this, '_updatePosition');
        this._tooltipContent.dispose();
        globalListener.unregister('itemTooltip', api);
    }
}

type TooltipableOption = {
    tooltip?: CommonTooltipOption<unknown>;
};
type TooltipModelOptionCascade =
    Model<TooltipableOption> | CommonTooltipOption<unknown> | string;
/**
 * From top to bottom. (the last one should be globalTooltipModel);
 */
function buildTooltipModel(
    modelCascade: TooltipModelOptionCascade[],
    globalTooltipModel: TooltipModel,
    defaultTooltipOption?: CommonTooltipOption<unknown>
): Model<TooltipOption & ComponentItemTooltipOption<unknown>> {
    // Last is always tooltip model.
    const ecModel = globalTooltipModel.ecModel;
    let resultModel: Model<TooltipOption & ComponentItemTooltipOption<unknown>>;

    if (defaultTooltipOption) {
        resultModel = new Model(defaultTooltipOption, ecModel, ecModel);
        resultModel = new Model(globalTooltipModel.option, resultModel, ecModel);
    }
    else {
        resultModel = globalTooltipModel as Model<TooltipOption & ComponentItemTooltipOption<unknown>>;
    }

    for (let i = modelCascade.length - 1; i >= 0; i--) {
        let tooltipOpt = modelCascade[i];
        if (tooltipOpt) {
            if (tooltipOpt instanceof Model) {
                tooltipOpt = (tooltipOpt as Model<TooltipableOption>).get('tooltip', true);
            }
            // In each data item tooltip can be simply write:
            // {
            //  value: 10,
            //  tooltip: 'Something you need to know'
            // }
            if (isString(tooltipOpt)) {
                tooltipOpt = {
                    formatter: tooltipOpt
                };
            }
            if (tooltipOpt) {
                resultModel = new Model(tooltipOpt, resultModel, ecModel);
            }
        }
    }

    return resultModel as Model<TooltipOption & ComponentItemTooltipOption<unknown>>;
}

function makeDispatchAction(payload: ShowTipPayload | HideTipPayload, api: ExtensionAPI) {
    return payload.dispatchAction || bind(api.dispatchAction, api);
}

function refixTooltipPosition(
    x: number, y: number,
    content: TooltipHTMLContent | TooltipRichContent,
    viewWidth: number, viewHeight: number,
    gapH: number, gapV: number
) {
    const size = content.getSize();
    const width = size[0];
    const height = size[1];

    if (gapH != null) {
        // Add extra 2 pixels for this case:
        // At present the "values" in defaut tooltip are using CSS `float: right`.
        // When the right edge of the tooltip box is on the right side of the
        // viewport, the `float` layout might push the "values" to the second line.
        if (x + width + gapH + 2 > viewWidth) {
            x -= width + gapH;
        }
        else {
            x += gapH;
        }
    }
    if (gapV != null) {
        if (y + height + gapV > viewHeight) {
            y -= height + gapV;
        }
        else {
            y += gapV;
        }
    }
    return [x, y];
}

function confineTooltipPosition(
    x: number, y: number,
    content: TooltipHTMLContent | TooltipRichContent,
    viewWidth: number,
    viewHeight: number
): [number, number] {
    const size = content.getSize();
    const width = size[0];
    const height = size[1];

    x = Math.min(x + width, viewWidth) - width;
    y = Math.min(y + height, viewHeight) - height;
    x = Math.max(x, 0);
    y = Math.max(y, 0);

    return [x, y];
}

function calcTooltipPosition(
    position: TooltipOption['position'],
    rect: ZRRectLike,
    contentSize: number[],
    borderWidth: number
): [number, number] {
    const domWidth = contentSize[0];
    const domHeight = contentSize[1];
    const offset = Math.ceil(Math.SQRT2 * borderWidth) + 8;
    let x = 0;
    let y = 0;
    const rectWidth = rect.width;
    const rectHeight = rect.height;
    switch (position) {
        case 'inside':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y + rectHeight / 2 - domHeight / 2;
            break;
        case 'top':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y - domHeight - offset;
            break;
        case 'bottom':
            x = rect.x + rectWidth / 2 - domWidth / 2;
            y = rect.y + rectHeight + offset;
            break;
        case 'left':
            x = rect.x - domWidth - offset;
            y = rect.y + rectHeight / 2 - domHeight / 2;
            break;
        case 'right':
            x = rect.x + rectWidth + offset;
            y = rect.y + rectHeight / 2 - domHeight / 2;
    }
    return [x, y];
}

function isCenterAlign(align: HorizontalAlign | VerticalAlign) {
    return align === 'center' || align === 'middle';
}

/**
 * Find target component by payload like:
 * ```js
 * { legendId: 'some_id', name: 'xxx' }
 * { toolboxIndex: 1, name: 'xxx' }
 * { geoName: 'some_name', name: 'xxx' }
 * ```
 * PENDING: at present only
 *
 * If not found, return null/undefined.
 */
function findComponentReference(
    payload: ShowTipPayload,
    ecModel: GlobalModel,
    api: ExtensionAPI
): {
    componentMainType: ComponentMainType;
    componentIndex: number;
    el: ECElement;
} {
    const { queryOptionMap } = preParseFinder(payload);
    const componentMainType = queryOptionMap.keys()[0];
    if (!componentMainType || componentMainType === 'series') {
        return;
    }

    const queryResult = queryReferringComponents(
        ecModel,
        componentMainType,
        queryOptionMap.get(componentMainType),
        { useDefault: false, enableAll: false, enableNone: false }
    );
    const model = queryResult.models[0];
    if (!model) {
        return;
    }

    const view = api.getViewOfComponentModel(model);
    let el: ECElement;
    view.group.traverse((subEl: ECElement) => {
        const tooltipConfig = getECData(subEl).tooltipConfig;
        if (tooltipConfig && tooltipConfig.name === payload.name) {
            el = subEl;
            return true; // stop
        }
    });

    if (el) {
        return {
            componentMainType,
            componentIndex: model.componentIndex,
            el
        };
    }
}

export default TooltipView;
