/*
* 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 zrender from 'zrender/src/zrender';
import {
    assert,
    each,
    isFunction,
    isObject,
    indexOf,
    bind,
    clone,
    setAsPrimitive,
    createCanvas,
    extend,
    HashMap,
    createHashMap,
    map,
    defaults,
    isDom,
    isArray,
    $override,
    noop
} from 'zrender/src/core/util';
import * as colorTool from 'zrender/src/tool/color';
import env from 'zrender/src/core/env';
import timsort from 'zrender/src/core/timsort';
import Eventful, { EventCallbackSingleParam } from 'zrender/src/core/Eventful';
import Element, { ElementEvent } from 'zrender/src/Element';
import GlobalModel, {QueryConditionKindA, GlobalModelSetOptionOpts} from '../model/Global';
import ExtensionAPI from './ExtensionAPI';
import CoordinateSystemManager from './CoordinateSystem';
import OptionManager from '../model/OptionManager';
import backwardCompat from '../preprocessor/backwardCompat';
import dataStack from '../processor/dataStack';
import ComponentModel from '../model/Component';
import SeriesModel from '../model/Series';
import ComponentView, {ComponentViewConstructor} from '../view/Component';
import ChartView, {ChartViewConstructor} from '../view/Chart';
import * as graphic from '../util/graphic';
import {getECData} from '../util/innerStore';
import {
    isHighDownDispatcher,
    HOVER_STATE_EMPHASIS,
    HOVER_STATE_BLUR,
    blurSeriesFromHighlightPayload,
    toggleSelectionFromPayload,
    updateSeriesElementSelection,
    getAllSelectedIndices,
    isSelectChangePayload,
    isHighDownPayload,
    HIGHLIGHT_ACTION_TYPE,
    DOWNPLAY_ACTION_TYPE,
    SELECT_ACTION_TYPE,
    UNSELECT_ACTION_TYPE,
    TOGGLE_SELECT_ACTION_TYPE,
    savePathStates,
    enterEmphasis,
    leaveEmphasis,
    leaveBlur,
    enterSelect,
    leaveSelect,
    enterBlur,
    allLeaveBlur,
    findComponentHighDownDispatchers,
    blurComponent,
    handleGlobalMouseOverForHighDown,
    handleGlboalMouseOutForHighDown
} from '../util/states';
import * as modelUtil from '../util/model';
import {throttle} from '../util/throttle';
import {seriesStyleTask, dataStyleTask, dataColorPaletteTask} from '../visual/style';
import loadingDefault from '../loading/default';
import Scheduler from './Scheduler';
import lightTheme from '../theme/light';
import darkTheme from '../theme/dark';
import {CoordinateSystemMaster, CoordinateSystemCreator, CoordinateSystemHostModel} from '../coord/CoordinateSystem';
import { parseClassType } from '../util/clazz';
import {ECEventProcessor} from '../util/ECEventProcessor';
import {
    Payload, ECElement, RendererType, ECActionEvent,
    ActionHandler, ActionInfo, OptionPreprocessor, PostUpdater,
    LoadingEffect, LoadingEffectCreator, StageHandlerInternal,
    StageHandlerOverallReset, StageHandler,
    ViewRootGroup, DimensionDefinitionLoose, ECEventData, ThemeOption,
    ECBasicOption,
    ECUnitOption,
    ZRColor,
    ComponentMainType,
    ComponentSubType,
    ColorString,
    SelectChangedPayload,
    ScaleDataValue,
    ZRElementEventName,
    ECElementEvent,
    AnimationOption
} from '../util/types';
import Displayable from 'zrender/src/graphic/Displayable';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
import { seriesSymbolTask, dataSymbolTask } from '../visual/symbol';
import { getVisualFromData, getItemVisualFromData } from '../visual/helper';
import { deprecateLog } from '../util/log';
import { handleLegacySelectEvents } from '../legacy/dataSelectAction';

import { registerExternalTransform } from '../data/helper/transform';
import { createLocaleObject, SYSTEM_LANG, LocaleOption } from './locale';

import type {EChartsOption} from '../export/option';
import { findEventDispatcher } from '../util/event';
import decal from '../visual/decal';
import CanvasPainter from 'zrender/src/canvas/Painter';
import SVGPainter from 'zrender/src/svg/Painter';
import geoSourceManager from '../coord/geo/geoSourceManager';
import lifecycle, {
    LifecycleEvents,
    UpdateLifecycleTransitionItem,
    UpdateLifecycleParams,
    UpdateLifecycleTransitionOpt
} from './lifecycle';

declare let global: any;

type ModelFinder = modelUtil.ModelFinder;

const hasWindow = typeof window !== 'undefined';

export const version = '5.1.2';

export const dependencies = {
    zrender: '5.1.1'
};

const TEST_FRAME_REMAIN_TIME = 1;

const PRIORITY_PROCESSOR_SERIES_FILTER = 800;
// Some data processors depends on the stack result dimension (to calculate data extent).
// So data stack stage should be in front of data processing stage.
const PRIORITY_PROCESSOR_DATASTACK = 900;
// "Data filter" will block the stream, so it should be
// put at the begining of data processing.
const PRIORITY_PROCESSOR_FILTER = 1000;
const PRIORITY_PROCESSOR_DEFAULT = 2000;
const PRIORITY_PROCESSOR_STATISTIC = 5000;

const PRIORITY_VISUAL_LAYOUT = 1000;
const PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
const PRIORITY_VISUAL_GLOBAL = 2000;
const PRIORITY_VISUAL_CHART = 3000;
const PRIORITY_VISUAL_COMPONENT = 4000;
// Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
// overwrite the viusal result of component (like `visualMap`)
// using data item specific setting (like itemStyle.xxx on data item)
const PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500;
// Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
// visual result like `symbolSize`.
const PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
const PRIORITY_VISUAL_BRUSH = 5000;
const PRIORITY_VISUAL_ARIA = 6000;
const PRIORITY_VISUAL_DECAL = 7000;

export const PRIORITY = {
    PROCESSOR: {
        FILTER: PRIORITY_PROCESSOR_FILTER,
        SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
        STATISTIC: PRIORITY_PROCESSOR_STATISTIC
    },
    VISUAL: {
        LAYOUT: PRIORITY_VISUAL_LAYOUT,
        PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
        GLOBAL: PRIORITY_VISUAL_GLOBAL,
        CHART: PRIORITY_VISUAL_CHART,
        POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
        COMPONENT: PRIORITY_VISUAL_COMPONENT,
        BRUSH: PRIORITY_VISUAL_BRUSH,
        CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
        ARIA: PRIORITY_VISUAL_ARIA,
        DECAL: PRIORITY_VISUAL_DECAL
    }
};

// Main process have three entries: `setOption`, `dispatchAction` and `resize`,
// where they must not be invoked nestedly, except the only case: invoke
// dispatchAction with updateMethod "none" in main process.
// This flag is used to carry out this rule.
// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
const IN_MAIN_PROCESS_KEY = '__flagInMainProcess' as const;
const PENDING_UPDATE = '__pendingUpdate' as const;
const STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus' as const;
const ACTION_REG = /^[a-zA-Z0-9_]+$/;

const CONNECT_STATUS_KEY = '__connectUpdateStatus' as const;
const CONNECT_STATUS_PENDING = 0 as const;
const CONNECT_STATUS_UPDATING = 1 as const;
const CONNECT_STATUS_UPDATED = 2 as const;
type ConnectStatus =
    typeof CONNECT_STATUS_PENDING
    | typeof CONNECT_STATUS_UPDATING
    | typeof CONNECT_STATUS_UPDATED;

export type SetOptionTransitionOpt = UpdateLifecycleTransitionOpt;
export type SetOptionTransitionOptItem = UpdateLifecycleTransitionItem;

export interface SetOptionOpts {
    notMerge?: boolean;
    lazyUpdate?: boolean;
    silent?: boolean;
    // Rule: only `id` mapped will be merged,
    // other components of the certain `mainType` will be removed.
    replaceMerge?: GlobalModelSetOptionOpts['replaceMerge'];
    transition?: SetOptionTransitionOpt
};


export interface ResizeOpts {
    width?: number | 'auto', // Can be 'auto' (the same as null/undefined)
    height?: number | 'auto', // Can be 'auto' (the same as null/undefined)
    animation?: AnimationOption
    silent?: boolean // by default false.
};

interface PostIniter {
    (chart: EChartsType): void
}

type EventMethodName = 'on' | 'off';
function createRegisterEventWithLowercaseECharts(method: EventMethodName) {
    return function (this: ECharts, ...args: any): ECharts {
        if (this.isDisposed()) {
            disposedWarning(this.id);
            return;
        }
        return toLowercaseNameAndCallEventful<ECharts>(this, method, args);
    };
}
function createRegisterEventWithLowercaseMessageCenter(method: EventMethodName) {
    return function (this: MessageCenter, ...args: any): MessageCenter {
        return toLowercaseNameAndCallEventful<MessageCenter>(this, method, args);
    };
}
function toLowercaseNameAndCallEventful<T>(host: T, method: EventMethodName, args: any): T {
    // `args[0]` is event name. Event name is all lowercase.
    args[0] = args[0] && args[0].toLowerCase();
    return Eventful.prototype[method].apply(host, args) as any;
}


class MessageCenter extends Eventful {}
const messageCenterProto = MessageCenter.prototype;
messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off');

// ---------------------------------------
// Internal method names for class ECharts
// ---------------------------------------
let prepare: (ecIns: ECharts) => void;
let prepareView: (ecIns: ECharts, isComponent: boolean) => void;
let updateDirectly: (
    ecIns: ECharts, method: string, payload: Payload, mainType: ComponentMainType, subType?: ComponentSubType
) => void;
type UpdateMethod = (this: ECharts, payload?: Payload, renderParams?: UpdateLifecycleParams) => void;
let updateMethods: {
    prepareAndUpdate: UpdateMethod,
    update: UpdateMethod,
    updateTransform: UpdateMethod,
    updateView: UpdateMethod,
    updateVisual: UpdateMethod,
    updateLayout: UpdateMethod
};
let doConvertPixel: (
    ecIns: ECharts,
    methodName: string,
    finder: ModelFinder,
    value: (number | number[]) | (ScaleDataValue | ScaleDataValue[])
) => (number | number[]);
let updateStreamModes: (ecIns: ECharts, ecModel: GlobalModel) => void;
let doDispatchAction: (this: ECharts, payload: Payload, silent: boolean) => void;
let flushPendingActions: (this: ECharts, silent: boolean) => void;
let triggerUpdatedEvent: (this: ECharts, silent: boolean) => void;
let bindRenderedEvent: (zr: zrender.ZRenderType, ecIns: ECharts) => void;
let bindMouseEvent: (zr: zrender.ZRenderType, ecIns: ECharts) => void;
let clearColorPalette: (ecModel: GlobalModel) => void;
let render: (
    ecIns: ECharts, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload, updateParams: UpdateLifecycleParams
) => void;
let renderComponents: (
    ecIns: ECharts, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload,
    updateParams: UpdateLifecycleParams, dirtyList?: ComponentView[]
) => void;
let renderSeries: (
    ecIns: ECharts, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload | 'remain',
    updateParams: UpdateLifecycleParams,
    dirtyMap?: {[uid: string]: any}
) => void;
let createExtensionAPI: (ecIns: ECharts) => ExtensionAPI;
let enableConnect: (ecIns: ECharts) => void;

let markStatusToUpdate: (ecIns: ECharts) => void;
let applyChangedStates: (ecIns: ECharts) => void;

type RenderedEventParam = { elapsedTime: number };
type ECEventDefinition = {
    [key in ZRElementEventName]: EventCallbackSingleParam<ECElementEvent>
} & {
    rendered: EventCallbackSingleParam<RenderedEventParam>
    finished: () => void | boolean
} & {
    // TODO: Use ECActionEvent
    [key: string]: (...args: unknown[]) => void | boolean
};
type EChartsInitOpts = {
    locale?: string | LocaleOption,
    renderer?: RendererType,
    devicePixelRatio?: number,
    useDirtyRect?: boolean,
    width?: number,
    height?: number
};
class ECharts extends Eventful<ECEventDefinition> {

    /**
     * @readonly
     */
    id: string;

    /**
     * Group id
     * @readonly
     */
    group: string;

    private _zr: zrender.ZRenderType;

    private _dom: HTMLElement;

    private _model: GlobalModel;

    private _throttledZrFlush: zrender.ZRenderType extends {flush: infer R} ? R : never;

    private _theme: ThemeOption;

    private _locale: LocaleOption;

    private _chartsViews: ChartView[] = [];

    private _chartsMap: {[viewId: string]: ChartView} = {};

    private _componentsViews: ComponentView[] = [];

    private _componentsMap: {[viewId: string]: ComponentView} = {};

    private _coordSysMgr: CoordinateSystemManager;

    private _api: ExtensionAPI;

    private _scheduler: Scheduler;

    private _messageCenter: MessageCenter;

    // Can't dispatch action during rendering procedure
    private _pendingActions: Payload[] = [];

    // We use never here so ECEventProcessor will not been exposed.
    // which may include many unexpected types won't be exposed in the types to developers.
    protected _$eventProcessor: never;

    private _disposed: boolean;

    private _loadingFX: LoadingEffect;


    private [PENDING_UPDATE]: {
        silent: boolean
        updateParams: UpdateLifecycleParams
    };
    private [IN_MAIN_PROCESS_KEY]: boolean;
    private [CONNECT_STATUS_KEY]: ConnectStatus;
    private [STATUS_NEEDS_UPDATE_KEY]: boolean;

    constructor(
        dom: HTMLElement,
        // Theme name or themeOption.
        theme?: string | ThemeOption,
        opts?: EChartsInitOpts
    ) {
        super(new ECEventProcessor());

        opts = opts || {};

        // Get theme by name
        if (typeof theme === 'string') {
            theme = themeStorage[theme] as object;
        }

        this._dom = dom;

        let defaultRenderer = 'canvas';
        let defaultUseDirtyRect = false;
        if (__DEV__) {
            const root = (
                /* eslint-disable-next-line */
                hasWindow ? window : global
            ) as any;

            defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;

            const devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__;
            defaultUseDirtyRect = devUseDirtyRect == null
                ? defaultUseDirtyRect
                : devUseDirtyRect;
        }

        const zr = this._zr = zrender.init(dom, {
            renderer: opts.renderer || defaultRenderer,
            devicePixelRatio: opts.devicePixelRatio,
            width: opts.width,
            height: opts.height,
            useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
        });

        // Expect 60 fps.
        this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);

        theme = clone(theme);
        theme && backwardCompat(theme as ECUnitOption, true);

        this._theme = theme;

        this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);

        this._coordSysMgr = new CoordinateSystemManager();

        const api = this._api = createExtensionAPI(this);

        // Sort on demand
        function prioritySortFunc(a: StageHandlerInternal, b: StageHandlerInternal): number {
            return a.__prio - b.__prio;
        }
        timsort(visualFuncs, prioritySortFunc);
        timsort(dataProcessorFuncs, prioritySortFunc);

        this._scheduler = new Scheduler(this, api, dataProcessorFuncs, visualFuncs);

        this._messageCenter = new MessageCenter();

        // Init mouse events
        this._initEvents();

        // In case some people write `window.onresize = chart.resize`
        this.resize = bind(this.resize, this);

        zr.animation.on('frame', this._onframe, this);

        bindRenderedEvent(zr, this);

        bindMouseEvent(zr, this);

        // ECharts instance can be used as value.
        setAsPrimitive(this);
    }

    private _onframe(): void {
        if (this._disposed) {
            return;
        }

        applyChangedStates(this);

        const scheduler = this._scheduler;

        // Lazy update
        if (this[PENDING_UPDATE]) {
            const silent = (this[PENDING_UPDATE] as any).silent;

            this[IN_MAIN_PROCESS_KEY] = true;

            prepare(this);
            updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams);

            // At present, in each frame, zrender performs:
            //   (1) animation step forward.
            //   (2) trigger('frame') (where this `_onframe` is called)
            //   (3) zrender flush (render).
            // If we do nothing here, since we use `setToFinal: true`, the step (3) above
            // will render the final state of the elements before the real animation started.
            this._zr.flush();

            this[IN_MAIN_PROCESS_KEY] = false;

            this[PENDING_UPDATE] = null;

            flushPendingActions.call(this, silent);

            triggerUpdatedEvent.call(this, silent);
        }
        // Avoid do both lazy update and progress in one frame.
        else if (scheduler.unfinished) {
            // Stream progress.
            let remainTime = TEST_FRAME_REMAIN_TIME;
            const ecModel = this._model;
            const api = this._api;
            scheduler.unfinished = false;
            do {
                const startTime = +new Date();

                scheduler.performSeriesTasks(ecModel);

                // Currently dataProcessorFuncs do not check threshold.
                scheduler.performDataProcessorTasks(ecModel);

                updateStreamModes(this, ecModel);

                // Do not update coordinate system here. Because that coord system update in
                // each frame is not a good user experience. So we follow the rule that
                // the extent of the coordinate system is determin in the first frame (the
                // frame is executed immedietely after task reset.
                // this._coordSysMgr.update(ecModel, api);

                // console.log('--- ec frame visual ---', remainTime);
                scheduler.performVisualTasks(ecModel);

                renderSeries(this, this._model, api, 'remain', {});

                remainTime -= (+new Date() - startTime);
            }
            while (remainTime > 0 && scheduler.unfinished);

            // Call flush explicitly for trigger finished event.
            if (!scheduler.unfinished) {
                this._zr.flush();
            }
            // Else, zr flushing be ensue within the same frame,
            // because zr flushing is after onframe event.
        }
    }

    getDom(): HTMLElement {
        return this._dom;
    }

    getId(): string {
        return this.id;
    }

    getZr(): zrender.ZRenderType {
        return this._zr;
    }

    /**
     * Usage:
     * chart.setOption(option, notMerge, lazyUpdate);
     * chart.setOption(option, {
     *     notMerge: ...,
     *     lazyUpdate: ...,
     *     silent: ...
     * });
     *
     * @param opts opts or notMerge.
     * @param opts.notMerge Default `false`.
     * @param opts.lazyUpdate Default `false`. Useful when setOption frequently.
     * @param opts.silent Default `false`.
     * @param opts.replaceMerge Default undefined.
     */
    // Expose to user full option.
    setOption<Opt extends ECBasicOption>(option: Opt, notMerge?: boolean, lazyUpdate?: boolean): void;
    setOption<Opt extends ECBasicOption>(option: Opt, opts?: SetOptionOpts): void;
    /* eslint-disable-next-line */
    setOption<Opt extends ECBasicOption>(option: Opt, notMerge?: boolean | SetOptionOpts, lazyUpdate?: boolean): void {
        if (__DEV__) {
            assert(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.');
        }
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        let silent;
        let replaceMerge;
        let transitionOpt: SetOptionTransitionOpt;
        if (isObject(notMerge)) {
            lazyUpdate = notMerge.lazyUpdate;
            silent = notMerge.silent;
            replaceMerge = notMerge.replaceMerge;
            transitionOpt = notMerge.transition;
            notMerge = notMerge.notMerge;
        }

        this[IN_MAIN_PROCESS_KEY] = true;

        if (!this._model || notMerge) {
            const optionManager = new OptionManager(this._api);
            const theme = this._theme;
            const ecModel = this._model = new GlobalModel();
            ecModel.scheduler = this._scheduler;
            ecModel.init(null, null, null, theme, this._locale, optionManager);
        }

        this._model.setOption(option as ECBasicOption, { replaceMerge }, optionPreprocessorFuncs);

        const updateParams = {
            seriesTransition: transitionOpt,
            optionChanged: true
        } as UpdateLifecycleParams;

        if (lazyUpdate) {
            this[PENDING_UPDATE] = {
                silent: silent,
                updateParams: updateParams
            };
            this[IN_MAIN_PROCESS_KEY] = false;

            // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
            // It should wake it up to make sure zrender start to render at the next frame.
            this.getZr().wakeUp();
        }
        else {
            prepare(this);

            updateMethods.update.call(this, null, updateParams);

            // Ensure zr refresh sychronously, and then pixel in canvas can be
            // fetched after `setOption`.
            this._zr.flush();

            this[PENDING_UPDATE] = null;
            this[IN_MAIN_PROCESS_KEY] = false;

            flushPendingActions.call(this, silent);
            triggerUpdatedEvent.call(this, silent);
        }
    }

    /**
     * @DEPRECATED
     */
    private setTheme(): void {
        console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
    }

    // We don't want developers to use getModel directly.
    private getModel(): GlobalModel {
        return this._model;
    }

    getOption(): ECBasicOption {
        return this._model && this._model.getOption() as ECBasicOption;
    }

    getWidth(): number {
        return this._zr.getWidth();
    }

    getHeight(): number {
        return this._zr.getHeight();
    }

    getDevicePixelRatio(): number {
        return (this._zr.painter as CanvasPainter).dpr
            /* eslint-disable-next-line */
            || (hasWindow && window.devicePixelRatio) || 1;
    }

    /**
     * Get canvas which has all thing rendered
     */
    getRenderedCanvas(opts?: {
        backgroundColor?: ZRColor
        pixelRatio?: number
    }): HTMLCanvasElement {
        if (!env.canvasSupported) {
            return;
        }
        opts = opts || {};
        return (this._zr.painter as CanvasPainter).getRenderedCanvas({
            backgroundColor: (opts.backgroundColor || this._model.get('backgroundColor')) as ColorString,
            pixelRatio: opts.pixelRatio || this.getDevicePixelRatio()
        });
    }

    /**
     * Get svg data url
     */
    getSvgDataURL(): string {
        if (!env.svgSupported) {
            return;
        }

        const zr = this._zr;
        const list = zr.storage.getDisplayList();
        // Stop animations
        each(list, function (el: Element) {
            el.stopAnimation(null, true);
        });

        return (zr.painter as SVGPainter).toDataURL();
    }

    getDataURL(opts?: {
        // file type 'png' by default
        type?: 'png' | 'jpg' | 'svg',
        pixelRatio?: number,
        backgroundColor?: ZRColor,
        // component type array
        excludeComponents?: ComponentMainType[]
    }): string {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        opts = opts || {};
        const excludeComponents = opts.excludeComponents;
        const ecModel = this._model;
        const excludesComponentViews: ComponentView[] = [];
        const self = this;

        each(excludeComponents, function (componentType) {
            ecModel.eachComponent({
                mainType: componentType
            }, function (component) {
                const view = self._componentsMap[component.__viewId];
                if (!view.group.ignore) {
                    excludesComponentViews.push(view);
                    view.group.ignore = true;
                }
            });
        });

        const url = this._zr.painter.getType() === 'svg'
            ? this.getSvgDataURL()
            : this.getRenderedCanvas(opts).toDataURL(
                'image/' + (opts && opts.type || 'png')
            );

        each(excludesComponentViews, function (view) {
            view.group.ignore = false;
        });

        return url;
    }

    getConnectedDataURL(opts?: {
        // file type 'png' by default
        type?: 'png' | 'jpg' | 'svg',
        pixelRatio?: number,
        backgroundColor?: ZRColor,
        connectedBackgroundColor?: ZRColor
        excludeComponents?: string[]
    }): string {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        if (!env.canvasSupported) {
            return;
        }
        const isSvg = opts.type === 'svg';
        const groupId = this.group;
        const mathMin = Math.min;
        const mathMax = Math.max;
        const MAX_NUMBER = Infinity;
        if (connectedGroups[groupId]) {
            let left = MAX_NUMBER;
            let top = MAX_NUMBER;
            let right = -MAX_NUMBER;
            let bottom = -MAX_NUMBER;
            const canvasList: {dom: HTMLCanvasElement | string, left: number, top: number}[] = [];
            const dpr = (opts && opts.pixelRatio) || this.getDevicePixelRatio();

            each(instances, function (chart, id) {
                if (chart.group === groupId) {
                    const canvas = isSvg
                        ? (chart.getZr().painter as SVGPainter).getSvgDom().innerHTML
                        : chart.getRenderedCanvas(clone(opts));
                    const boundingRect = chart.getDom().getBoundingClientRect();
                    left = mathMin(boundingRect.left, left);
                    top = mathMin(boundingRect.top, top);
                    right = mathMax(boundingRect.right, right);
                    bottom = mathMax(boundingRect.bottom, bottom);
                    canvasList.push({
                        dom: canvas,
                        left: boundingRect.left,
                        top: boundingRect.top
                    });
                }
            });

            left *= dpr;
            top *= dpr;
            right *= dpr;
            bottom *= dpr;
            const width = right - left;
            const height = bottom - top;
            const targetCanvas = createCanvas();
            const zr = zrender.init(targetCanvas, {
                renderer: isSvg ? 'svg' : 'canvas'
            });
            zr.resize({
                width: width,
                height: height
            });

            if (isSvg) {
                let content = '';
                each(canvasList, function (item) {
                    const x = item.left - left;
                    const y = item.top - top;
                    content += '<g transform="translate(' + x + ','
                        + y + ')">' + item.dom + '</g>';
                });
                (zr.painter as SVGPainter).getSvgRoot().innerHTML = content;

                if (opts.connectedBackgroundColor) {
                    (zr.painter as SVGPainter).setBackgroundColor(opts.connectedBackgroundColor as string);
                }

                zr.refreshImmediately();
                return (zr.painter as SVGPainter).toDataURL();
            }
            else {
                // Background between the charts
                if (opts.connectedBackgroundColor) {
                    zr.add(new graphic.Rect({
                        shape: {
                            x: 0,
                            y: 0,
                            width: width,
                            height: height
                        },
                        style: {
                            fill: opts.connectedBackgroundColor
                        }
                    }));
                }

                each(canvasList, function (item) {
                    const img = new graphic.Image({
                        style: {
                            x: item.left * dpr - left,
                            y: item.top * dpr - top,
                            image: item.dom
                        }
                    });
                    zr.add(img);
                });
                zr.refreshImmediately();

                return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
            }
        }
        else {
            return this.getDataURL(opts);
        }
    }

    /**
     * Convert from logical coordinate system to pixel coordinate system.
     * See CoordinateSystem#convertToPixel.
     */
    convertToPixel(finder: ModelFinder, value: ScaleDataValue): number;
    convertToPixel(finder: ModelFinder, value: ScaleDataValue[]): number[];
    convertToPixel(finder: ModelFinder, value: ScaleDataValue | ScaleDataValue[]): number | number[] {
        return doConvertPixel(this, 'convertToPixel', finder, value);
    }

    /**
     * Convert from pixel coordinate system to logical coordinate system.
     * See CoordinateSystem#convertFromPixel.
     */
    convertFromPixel(finder: ModelFinder, value: number): number;
    convertFromPixel(finder: ModelFinder, value: number[]): number[];
    convertFromPixel(finder: ModelFinder, value: number | number[]): number | number[] {
        return doConvertPixel(this, 'convertFromPixel', finder, value);
    }

    /**
     * Is the specified coordinate systems or components contain the given pixel point.
     * @param {Array|number} value
     * @return {boolean} result
     */
    containPixel(finder: ModelFinder, value: number[]): boolean {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        const ecModel = this._model;
        let result: boolean;

        const findResult = modelUtil.parseFinder(ecModel, finder);

        each(findResult, function (models, key) {
            key.indexOf('Models') >= 0 && each(models as ComponentModel[], function (model) {
                const coordSys = (model as CoordinateSystemHostModel).coordinateSystem;
                if (coordSys && coordSys.containPoint) {
                    result = result || !!coordSys.containPoint(value);
                }
                else if (key === 'seriesModels') {
                    const view = this._chartsMap[model.__viewId];
                    if (view && view.containPoint) {
                        result = result || view.containPoint(value, model as SeriesModel);
                    }
                    else {
                        if (__DEV__) {
                            console.warn(key + ': ' + (view
                                ? 'The found component do not support containPoint.'
                                : 'No view mapping to the found component.'
                            ));
                        }
                    }
                }
                else {
                    if (__DEV__) {
                        console.warn(key + ': containPoint is not supported');
                    }
                }
            }, this);
        }, this);

        return !!result;
    }

    /**
     * Get visual from series or data.
     * @param finder
     *        If string, e.g., 'series', means {seriesIndex: 0}.
     *        If Object, could contain some of these properties below:
     *        {
     *            seriesIndex / seriesId / seriesName,
     *            dataIndex / dataIndexInside
     *        }
     *        If dataIndex is not specified, series visual will be fetched,
     *        but not data item visual.
     *        If all of seriesIndex, seriesId, seriesName are not specified,
     *        visual will be fetched from first series.
     * @param visualType 'color', 'symbol', 'symbolSize'
     */
    getVisual(finder: ModelFinder, visualType: string) {
        const ecModel = this._model;

        const parsedFinder = modelUtil.parseFinder(ecModel, finder, {
            defaultMainType: 'series'
        }) as modelUtil.ParsedModelFinderKnown;

        const seriesModel = parsedFinder.seriesModel;

        if (__DEV__) {
            if (!seriesModel) {
                console.warn('There is no specified seires model');
            }
        }

        const data = seriesModel.getData();

        const dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside')
            ? parsedFinder.dataIndexInside
            : parsedFinder.hasOwnProperty('dataIndex')
            ? data.indexOfRawIndex(parsedFinder.dataIndex)
            : null;

        return dataIndexInside != null
            ? getItemVisualFromData(data, dataIndexInside, visualType)
            : getVisualFromData(data, visualType);
    }

    /**
     * Get view of corresponding component model
     */
    private getViewOfComponentModel(componentModel: ComponentModel): ComponentView {
        return this._componentsMap[componentModel.__viewId];
    }

    /**
     * Get view of corresponding series model
     */
    private getViewOfSeriesModel(seriesModel: SeriesModel): ChartView {
        return this._chartsMap[seriesModel.__viewId];
    }


    private _initEvents(): void {
        each(MOUSE_EVENT_NAMES, (eveName) => {
            const handler = (e: ElementEvent) => {
                const ecModel = this.getModel();
                const el = e.target;
                let params: ECElementEvent;
                const isGlobalOut = eveName === 'globalout';
                // no e.target when 'globalout'.
                if (isGlobalOut) {
                    params = {} as ECElementEvent;
                }
                else {
                    el && findEventDispatcher(el, (parent) => {
                        const ecData = getECData(parent);
                        if (ecData && ecData.dataIndex != null) {
                            const dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
                            params = (
                                dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {}
                            ) as ECElementEvent;
                            return true;
                        }
                        // If element has custom eventData of components
                        else if (ecData.eventData) {
                            params = extend({}, ecData.eventData) as ECElementEvent;
                            return true;
                        }
                    }, true);
                }

                // Contract: if params prepared in mouse event,
                // these properties must be specified:
                // {
                //    componentType: string (component main type)
                //    componentIndex: number
                // }
                // Otherwise event query can not work.

                if (params) {
                    let componentType = params.componentType;
                    let componentIndex = params.componentIndex;
                    // Special handling for historic reason: when trigger by
                    // markLine/markPoint/markArea, the componentType is
                    // 'markLine'/'markPoint'/'markArea', but we should better
                    // enable them to be queried by seriesIndex, since their
                    // option is set in each series.
                    if (componentType === 'markLine'
                        || componentType === 'markPoint'
                        || componentType === 'markArea'
                    ) {
                        componentType = 'series';
                        componentIndex = params.seriesIndex;
                    }
                    const model = componentType && componentIndex != null
                        && ecModel.getComponent(componentType, componentIndex);
                    const view = model && this[
                        model.mainType === 'series' ? '_chartsMap' : '_componentsMap'
                    ][model.__viewId];

                    if (__DEV__) {
                        // `event.componentType` and `event[componentTpype + 'Index']` must not
                        // be missed, otherwise there is no way to distinguish source component.
                        // See `dataFormat.getDataParams`.
                        if (!isGlobalOut && !(model && view)) {
                            console.warn('model or view can not be found by params');
                        }
                    }

                    params.event = e;
                    params.type = eveName;

                    (this._$eventProcessor as ECEventProcessor).eventInfo = {
                        targetEl: el,
                        packedEvent: params,
                        model: model,
                        view: view
                    };

                    this.trigger(eveName, params);
                }
            };
            // Consider that some component (like tooltip, brush, ...)
            // register zr event handler, but user event handler might
            // do anything, such as call `setOption` or `dispatchAction`,
            // which probably update any of the content and probably
            // cause problem if it is called previous other inner handlers.
            (handler as any).zrEventfulCallAtLast = true;
            this._zr.on(eveName, handler, this);
        });

        each(eventActionMap, (actionType, eventType) => {
            this._messageCenter.on(eventType, function (event: Payload) {
                (this as any).trigger(eventType, event);
            }, this);
        });

        // Extra events
        // TODO register?
        each(
            ['selectchanged'],
            (eventType) => {
                this._messageCenter.on(eventType, function (event: Payload) {
                    (this as any).trigger(eventType, event);
                }, this);
            }
        );

        handleLegacySelectEvents(this._messageCenter, this, this._api);
    }

    isDisposed(): boolean {
        return this._disposed;
    }

    clear(): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }
        this.setOption({ series: [] } as EChartsOption, true);
    }

    dispose(): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }
        this._disposed = true;

        modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');

        const chart = this;
        const api = chart._api;
        const ecModel = chart._model;

        each(chart._componentsViews, function (component) {
            component.dispose(ecModel, api);
        });
        each(chart._chartsViews, function (chart) {
            chart.dispose(ecModel, api);
        });

        // Dispose after all views disposed
        chart._zr.dispose();

        // Set properties to null.
        // To reduce the memory cost in case the top code still holds this instance unexpectedly.
        chart._dom =
        chart._model =
        chart._chartsMap =
        chart._componentsMap =
        chart._chartsViews =
        chart._componentsViews =
        chart._scheduler =
        chart._api =
        chart._zr =
        chart._throttledZrFlush =
        chart._theme =
        chart._coordSysMgr =
        chart._messageCenter = null;

        delete instances[chart.id];
    }

    /**
     * Resize the chart
     */
    resize(opts?: ResizeOpts): void {
        if (__DEV__) {
            assert(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
        }
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        this._zr.resize(opts);

        const ecModel = this._model;

        // Resize loading effect
        this._loadingFX && this._loadingFX.resize();

        if (!ecModel) {
            return;
        }

        let needPrepare = ecModel.resetOption('media');

        let silent = opts && opts.silent;

        // There is some real cases that:
        // chart.setOption(option, { lazyUpdate: true });
        // chart.resize();
        if (this[PENDING_UPDATE]) {
            if (silent == null) {
                silent = (this[PENDING_UPDATE] as any).silent;
            }
            needPrepare = true;
            this[PENDING_UPDATE] = null;
        }

        this[IN_MAIN_PROCESS_KEY] = true;

        needPrepare && prepare(this);

        updateMethods.update.call(this, {
            type: 'resize',
            animation: extend({
                // Disable animation
                duration: 0
            }, opts && opts.animation)
        });

        this[IN_MAIN_PROCESS_KEY] = false;

        flushPendingActions.call(this, silent);

        triggerUpdatedEvent.call(this, silent);
    }

    /**
     * Show loading effect
     * @param name 'default' by default
     * @param cfg cfg of registered loading effect
     */
    showLoading(cfg?: object): void;
    showLoading(name?: string, cfg?: object): void;
    showLoading(name?: string | object, cfg?: object): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        if (isObject(name)) {
            cfg = name as object;
            name = '';
        }
        name = name || 'default';

        this.hideLoading();
        if (!loadingEffects[name]) {
            if (__DEV__) {
                console.warn('Loading effects ' + name + ' not exists.');
            }
            return;
        }
        const el = loadingEffects[name](this._api, cfg);
        const zr = this._zr;
        this._loadingFX = el;

        zr.add(el);
    }

    /**
     * Hide loading effect
     */
    hideLoading(): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        this._loadingFX && this._zr.remove(this._loadingFX);
        this._loadingFX = null;
    }

    makeActionFromEvent(eventObj: ECActionEvent): Payload {
        const payload = extend({}, eventObj) as Payload;
        payload.type = eventActionMap[eventObj.type];
        return payload;
    }

    /**
     * @param opt If pass boolean, means opt.silent
     * @param opt.silent Default `false`. Whether trigger events.
     * @param opt.flush Default `undefined`.
     *        true: Flush immediately, and then pixel in canvas can be fetched
     *            immediately. Caution: it might affect performance.
     *        false: Not flush.
     *        undefined: Auto decide whether perform flush.
     */
    dispatchAction(
        payload: Payload,
        opt?: boolean | {
            silent?: boolean,
            flush?: boolean | undefined
        }
    ): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        if (!isObject(opt)) {
            opt = {silent: !!opt};
        }

        if (!actions[payload.type]) {
            return;
        }

        // Avoid dispatch action before setOption. Especially in `connect`.
        if (!this._model) {
            return;
        }

        // May dispatchAction in rendering procedure
        if (this[IN_MAIN_PROCESS_KEY]) {
            this._pendingActions.push(payload);
            return;
        }

        const silent = opt.silent;
        doDispatchAction.call(this, payload, silent);

        const flush = opt.flush;
        if (flush) {
            this._zr.flush();
        }
        else if (flush !== false && env.browser.weChat) {
            // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
            // hang when sliding page (on touch event), which cause that zr does not
            // refresh util user interaction finished, which is not expected.
            // But `dispatchAction` may be called too frequently when pan on touch
            // screen, which impacts performance if do not throttle them.
            this._throttledZrFlush();
        }

        flushPendingActions.call(this, silent);

        triggerUpdatedEvent.call(this, silent);
    }

    updateLabelLayout() {
        lifecycle.trigger('series:layoutlabels', this._model, this._api, {
            // Not adding series labels.
            // TODO
            updatedSeries: []
        });
    }

    appendData(params: {
        seriesIndex: number,
        data: any
    }): void {
        if (this._disposed) {
            disposedWarning(this.id);
            return;
        }

        const seriesIndex = params.seriesIndex;
        const ecModel = this.getModel();
        const seriesModel = ecModel.getSeriesByIndex(seriesIndex) as SeriesModel;

        if (__DEV__) {
            assert(params.data && seriesModel);
        }

        seriesModel.appendData(params);

        // Note: `appendData` does not support that update extent of coordinate
        // system, util some scenario require that. In the expected usage of
        // `appendData`, the initial extent of coordinate system should better
        // be fixed by axis `min`/`max` setting or initial data, otherwise if
        // the extent changed while `appendData`, the location of the painted
        // graphic elements have to be changed, which make the usage of
        // `appendData` meaningless.

        this._scheduler.unfinished = true;

        this.getZr().wakeUp();
    }


    // A work around for no `internal` modifier in ts yet but
    // need to strictly hide private methods to JS users.
    private static internalField = (function () {

        prepare = function (ecIns: ECharts): void {
            const scheduler = ecIns._scheduler;

            scheduler.restorePipelines(ecIns._model);
            scheduler.prepareStageTasks();

            prepareView(ecIns, true);
            prepareView(ecIns, false);

            scheduler.plan();
        };

        /**
         * Prepare view instances of charts and components
         */
        prepareView = function (ecIns: ECharts, isComponent: boolean): void {
            const ecModel = ecIns._model;
            const scheduler = ecIns._scheduler;
            const viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
            const viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
            const zr = ecIns._zr;
            const api = ecIns._api;

            for (let i = 0; i < viewList.length; i++) {
                viewList[i].__alive = false;
            }

            isComponent
                ? ecModel.eachComponent(function (componentType, model) {
                    componentType !== 'series' && doPrepare(model);
                })
                : ecModel.eachSeries(doPrepare);

            function doPrepare(model: ComponentModel): void {
                // By defaut view will be reused if possible for the case that `setOption` with "notMerge"
                // mode and need to enable transition animation. (Usually, when they have the same id, or
                // especially no id but have the same type & name & index. See the `model.id` generation
                // rule in `makeIdAndName` and `viewId` generation rule here).
                // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that
                // the new model has nothing to do with the old model.
                const requireNewView = model.__requireNewView;
                // This command should not work twice.
                model.__requireNewView = false;
                // Consider: id same and type changed.
                const viewId = '_ec_' + model.id + '_' + model.type;
                let view = !requireNewView && viewMap[viewId];
                if (!view) {
                    const classType = parseClassType(model.type);
                    const Clazz = isComponent
                        ? (ComponentView as ComponentViewConstructor).getClass(classType.main, classType.sub)
                        : (
                            // FIXME:TS
                            // (ChartView as ChartViewConstructor).getClass('series', classType.sub)
                            // For backward compat, still support a chart type declared as only subType
                            // like "liquidfill", but recommend "series.liquidfill"
                            // But need a base class to make a type series.
                            (ChartView as ChartViewConstructor).getClass(classType.sub)
                        );

                    if (__DEV__) {
                        assert(Clazz, classType.sub + ' does not exist.');
                    }

                    view = new Clazz();
                    view.init(ecModel, api);
                    viewMap[viewId] = view;
                    viewList.push(view as any);
                    zr.add(view.group);
                }

                model.__viewId = view.__id = viewId;
                view.__alive = true;
                view.__model = model;
                view.group.__ecComponentInfo = {
                    mainType: model.mainType,
                    index: model.componentIndex
                };
                !isComponent && scheduler.prepareView(
                    view as ChartView, model as SeriesModel, ecModel, api
                );
            }

            for (let i = 0; i < viewList.length;) {
                const view = viewList[i];
                if (!view.__alive) {
                    !isComponent && (view as ChartView).renderTask.dispose();
                    zr.remove(view.group);
                    view.dispose(ecModel, api);
                    viewList.splice(i, 1);
                    if (viewMap[view.__id] === view) {
                        delete viewMap[view.__id];
                    }
                    view.__id = view.group.__ecComponentInfo = null;
                }
                else {
                    i++;
                }
            }
        };

        updateDirectly = function (
            ecIns: ECharts,
            method: string,
            payload: Payload,
            mainType: ComponentMainType,
            subType?: ComponentSubType
        ): void {
            const ecModel = ecIns._model;

            ecModel.setUpdatePayload(payload);

            // broadcast
            if (!mainType) {
                // FIXME
                // Chart will not be update directly here, except set dirty.
                // But there is no such scenario now.
                each([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
                return;
            }

            const query: QueryConditionKindA['query'] = {};
            query[mainType + 'Id'] = payload[mainType + 'Id'];
            query[mainType + 'Index'] = payload[mainType + 'Index'];
            query[mainType + 'Name'] = payload[mainType + 'Name'];

            const condition = {mainType: mainType, query: query} as QueryConditionKindA;
            subType && (condition.subType = subType); // subType may be '' by parseClassType;

            const excludeSeriesId = payload.excludeSeriesId;
            let excludeSeriesIdMap: HashMap<true, string>;
            if (excludeSeriesId != null) {
                excludeSeriesIdMap = createHashMap();
                each(modelUtil.normalizeToArray(excludeSeriesId), id => {
                    const modelId = modelUtil.convertOptionIdName(id, null);
                    if (modelId != null) {
                        excludeSeriesIdMap.set(modelId, true);
                    }
                });
            }

            if (isHighDownPayload(payload)) {
                allLeaveBlur(ecIns._api);
            }

            // If dispatchAction before setOption, do nothing.
            ecModel && ecModel.eachComponent(condition, function (model) {
                const isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null;
                if (isExcluded) {
                    return;
                };
                if (isHighDownPayload(payload)) {
                    if (model instanceof SeriesModel) {
                        if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur) {
                            blurSeriesFromHighlightPayload(model, payload, ecIns._api);
                        }
                    }
                    else {
                        const { focusSelf, dispatchers } = findComponentHighDownDispatchers(
                            model.mainType, model.componentIndex, payload.name, ecIns._api
                        );
                        if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) {
                            blurComponent(model.mainType, model.componentIndex, ecIns._api);
                        }
                        // PENDING:
                        // Whether to put this "enter emphasis" code in `ComponentView`,
                        // which will be the same as `ChartView` but might be not necessary
                        // and will be far from this logic.
                        if (dispatchers) {
                            each(dispatchers, dispatcher => {
                                payload.type === HIGHLIGHT_ACTION_TYPE
                                    ? enterEmphasis(dispatcher)
                                    : leaveEmphasis(dispatcher);
                            });
                        }
                    }
                }
                else if (isSelectChangePayload(payload)) {
                    // TODO geo
                    if (model instanceof SeriesModel) {
                        toggleSelectionFromPayload(model, payload, ecIns._api);
                        updateSeriesElementSelection(model);
                        markStatusToUpdate(ecIns);
                    }
                }
            }, ecIns);

            ecModel && ecModel.eachComponent(condition, function (model) {
                const isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null;
                if (isExcluded) {
                    return;
                };
                callView(ecIns[
                    mainType === 'series' ? '_chartsMap' : '_componentsMap'
                ][model.__viewId]);
            }, ecIns);

            function callView(view: ComponentView | ChartView) {
                view && view.__alive && (view as any)[method] && (view as any)[method](
                    view.__model, ecModel, ecIns._api, payload
                );
            }
        };

        updateMethods = {

            prepareAndUpdate(this: ECharts, payload: Payload): void {
                prepare(this);
                updateMethods.update.call(this, payload, {
                    // Needs to mark option changed if newOption is given.
                    // It's from MagicType.
                    // TODO If use a separate flag optionChanged in payload?
                    optionChanged: payload.newOption != null
                });
            },

            update(this: ECharts, payload: Payload, updateParams: UpdateLifecycleParams): void {
                const ecModel = this._model;
                const api = this._api;
                const zr = this._zr;
                const coordSysMgr = this._coordSysMgr;
                const scheduler = this._scheduler;

                // update before setOption
                if (!ecModel) {
                    return;
                }

                ecModel.setUpdatePayload(payload);

                scheduler.restoreData(ecModel, payload);

                scheduler.performSeriesTasks(ecModel);

                // TODO
                // Save total ecModel here for undo/redo (after restoring data and before processing data).
                // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.

                // Create new coordinate system each update
                // In LineView may save the old coordinate system and use it to get the orignal point
                coordSysMgr.create(ecModel, api);

                scheduler.performDataProcessorTasks(ecModel, payload);

                // Current stream render is not supported in data process. So we can update
                // stream modes after data processing, where the filtered data is used to
                // deteming whether use progressive rendering.
                updateStreamModes(this, ecModel);

                // We update stream modes before coordinate system updated, then the modes info
                // can be fetched when coord sys updating (consider the barGrid extent fix). But
                // the drawback is the full coord info can not be fetched. Fortunately this full
                // coord is not requied in stream mode updater currently.
                coordSysMgr.update(ecModel, api);

                clearColorPalette(ecModel);
                scheduler.performVisualTasks(ecModel, payload);

                render(this, ecModel, api, payload, updateParams);

                // Set background
                let backgroundColor = ecModel.get('backgroundColor') || 'transparent';
                const darkMode = ecModel.get('darkMode');

                // In IE8
                if (!env.canvasSupported) {
                    const colorArr = colorTool.parse(backgroundColor as ColorString);
                    backgroundColor = colorTool.stringify(colorArr, 'rgb');
                    if (colorArr[3] === 0) {
                        backgroundColor = 'transparent';
                    }
                }
                else {
                    zr.setBackgroundColor(backgroundColor);

                    // Force set dark mode.
                    if (darkMode != null && darkMode !== 'auto') {
                        zr.setDarkMode(darkMode);
                    }
                }

                lifecycle.trigger('afterupdate', ecModel, api);
            },

            updateTransform(this: ECharts, payload: Payload): void {
                const ecModel = this._model;
                const api = this._api;

                // update before setOption
                if (!ecModel) {
                    return;
                }

                ecModel.setUpdatePayload(payload);

                // ChartView.markUpdateMethod(payload, 'updateTransform');

                const componentDirtyList = [];
                ecModel.eachComponent((componentType, componentModel) => {
                    if (componentType === 'series') {
                        return;
                    }

                    const componentView = this.getViewOfComponentModel(componentModel);
                    if (componentView && componentView.__alive) {
                        if (componentView.updateTransform) {
                            const result = componentView.updateTransform(componentModel, ecModel, api, payload);
                            result && result.update && componentDirtyList.push(componentView);
                        }
                        else {
                            componentDirtyList.push(componentView);
                        }
                    }
                });

                const seriesDirtyMap = createHashMap();
                ecModel.eachSeries((seriesModel) => {
                    const chartView = this._chartsMap[seriesModel.__viewId];
                    if (chartView.updateTransform) {
                        const result = chartView.updateTransform(seriesModel, ecModel, api, payload);
                        result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
                    }
                    else {
                        seriesDirtyMap.set(seriesModel.uid, 1);
                    }
                });

                clearColorPalette(ecModel);
                // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
                // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
                this._scheduler.performVisualTasks(
                    ecModel, payload, {setDirty: true, dirtyMap: seriesDirtyMap}
                );

                // Currently, not call render of components. Geo render cost a lot.
                // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);
                renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap);

                lifecycle.trigger('afterupdate', ecModel, api);
            },

            updateView(this: ECharts, payload: Payload): void {
                const ecModel = this._model;

                // update before setOption
                if (!ecModel) {
                    return;
                }

                ecModel.setUpdatePayload(payload);

                ChartView.markUpdateMethod(payload, 'updateView');

                clearColorPalette(ecModel);

                // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
                this._scheduler.performVisualTasks(ecModel, payload, {setDirty: true});

                render(this, ecModel, this._api, payload, {});

                lifecycle.trigger('afterupdate', ecModel, this._api);
            },

            updateVisual(this: ECharts, payload: Payload): void {
                // updateMethods.update.call(this, payload);

                const ecModel = this._model;

                // update before setOption
                if (!ecModel) {
                    return;
                }

                ecModel.setUpdatePayload(payload);

                // clear all visual
                ecModel.eachSeries(function (seriesModel) {
                    seriesModel.getData().clearAllVisual();
                });

                // Perform visual
                ChartView.markUpdateMethod(payload, 'updateVisual');

                clearColorPalette(ecModel);

                // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
                this._scheduler.performVisualTasks(ecModel, payload, {visualType: 'visual', setDirty: true});

                ecModel.eachComponent((componentType, componentModel) => {  // TODO componentType may be series.
                    if (componentType !== 'series') {
                        const componentView = this.getViewOfComponentModel(componentModel);
                        componentView && componentView.__alive
                            && componentView.updateVisual(componentModel, ecModel, this._api, payload);
                    }
                });

                ecModel.eachSeries((seriesModel) => {
                    const chartView = this._chartsMap[seriesModel.__viewId];
                    chartView.updateVisual(seriesModel, ecModel, this._api, payload);
                });

                lifecycle.trigger('afterupdate', ecModel, this._api);
            },

            updateLayout(this: ECharts, payload: Payload): void {
                updateMethods.update.call(this, payload);
            }
        };

        doConvertPixel = function (
            ecIns: ECharts,
            methodName: 'convertFromPixel' | 'convertToPixel',
            finder: ModelFinder,
            value: (number | number[]) | (ScaleDataValue | ScaleDataValue[])
        ): (number | number[]) {
            if (ecIns._disposed) {
                disposedWarning(ecIns.id);
                return;
            }
            const ecModel = ecIns._model;
            const coordSysList = ecIns._coordSysMgr.getCoordinateSystems();
            let result;

            const parsedFinder = modelUtil.parseFinder(ecModel, finder);

            for (let i = 0; i < coordSysList.length; i++) {
                const coordSys = coordSysList[i];
                if (coordSys[methodName]
                    && (result = coordSys[methodName](ecModel, parsedFinder, value as any)) != null
                ) {
                    return result;
                }
            }

            if (__DEV__) {
                console.warn(
                    'No coordinate system that supports ' + methodName + ' found by the given finder.'
                );
            }
        };

        updateStreamModes = function (ecIns: ECharts, ecModel: GlobalModel): void {
            const chartsMap = ecIns._chartsMap;
            const scheduler = ecIns._scheduler;
            ecModel.eachSeries(function (seriesModel) {
                scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
            });
        };

        doDispatchAction = function (this: ECharts, payload: Payload, silent: boolean): void {
            const ecModel = this.getModel();
            const payloadType = payload.type;
            const escapeConnect = payload.escapeConnect;
            const actionWrap = actions[payloadType];
            const actionInfo = actionWrap.actionInfo;

            const cptTypeTmp = (actionInfo.update || 'update').split(':');
            const updateMethod = cptTypeTmp.pop();
            const cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);

            this[IN_MAIN_PROCESS_KEY] = true;

            let payloads: Payload[] = [payload];
            let batched = false;
            // Batch action
            if (payload.batch) {
                batched = true;
                payloads = map<Payload['batch'][0], Payload, unknown>(payload.batch, function (item) {
                    item = defaults(extend({}, item), payload);
                    item.batch = null;
                    return item as Payload;
                });
            }

            const eventObjBatch: ECEventData[] = [];
            let eventObj: ECActionEvent;

            const isSelectChange = isSelectChangePayload(payload);
            const isHighDown = isHighDownPayload(payload);

            each(payloads, (batchItem) => {
                // Action can specify the event by return it.
                eventObj = actionWrap.action(batchItem, this._model, this._api) as ECActionEvent;
                // Emit event outside
                eventObj = eventObj || extend({} as ECActionEvent, batchItem);
                // Convert type to eventType
                eventObj.type = actionInfo.event || eventObj.type;
                eventObjBatch.push(eventObj);

                // light update does not perform data process, layout and visual.
                if (isHighDown) {
                    const { queryOptionMap, mainTypeSpecified } = modelUtil.preParseFinder(payload as ModelFinder);
                    const componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series';
                    updateDirectly(this, updateMethod, batchItem as Payload, componentMainType);
                    markStatusToUpdate(this);
                }
                else if (isSelectChange) {
                    // At present `dispatchAction({ type: 'select', ... })` is not supported on components.
                    // geo still use 'geoselect'.
                    updateDirectly(this, updateMethod, batchItem as Payload, 'series');
                    markStatusToUpdate(this);
                }
                else if (cptType) {
                    updateDirectly(this, updateMethod, batchItem as Payload, cptType.main, cptType.sub);
                }
            });

            if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) {
                // Still dirty
                if (this[PENDING_UPDATE]) {
                    prepare(this);
                    updateMethods.update.call(this, payload);
                    this[PENDING_UPDATE] = null;
                }
                else {
                    updateMethods[updateMethod as keyof typeof updateMethods].call(this, payload);
                }
            }

            // Follow the rule of action batch
            if (batched) {
                eventObj = {
                    type: actionInfo.event || payloadType,
                    escapeConnect: escapeConnect,
                    batch: eventObjBatch
                };
            }
            else {
                eventObj = eventObjBatch[0] as ECActionEvent;
            }

            this[IN_MAIN_PROCESS_KEY] = false;

            if (!silent) {
                const messageCenter = this._messageCenter;
                messageCenter.trigger(eventObj.type, eventObj);
                // Extra triggered 'selectchanged' event
                if (isSelectChange) {
                    const newObj: SelectChangedPayload = {
                        type: 'selectchanged',
                        escapeConnect: escapeConnect,
                        selected: getAllSelectedIndices(ecModel),
                        isFromClick: payload.isFromClick || false,
                        fromAction: payload.type as 'select' | 'unselect' | 'toggleSelected',
                        fromActionPayload: payload
                    };
                    messageCenter.trigger(newObj.type, newObj);
                }
            }
        };

        flushPendingActions = function (this: ECharts, silent: boolean): void {
            const pendingActions = this._pendingActions;
            while (pendingActions.length) {
                const payload = pendingActions.shift();
                doDispatchAction.call(this, payload, silent);
            }
        };

        triggerUpdatedEvent = function (this: ECharts, silent): void {
            !silent && this.trigger('updated');
        };

        /**
         * Event `rendered` is triggered when zr
         * rendered. It is useful for realtime
         * snapshot (reflect animation).
         *
         * Event `finished` is triggered when:
         * (1) zrender rendering finished.
         * (2) initial animation finished.
         * (3) progressive rendering finished.
         * (4) no pending action.
         * (5) no delayed setOption needs to be processed.
         */
        bindRenderedEvent = function (zr: zrender.ZRenderType, ecIns: ECharts): void {
            zr.on('rendered', function (params: RenderedEventParam) {

                ecIns.trigger('rendered', params);

                // The `finished` event should not be triggered repeatly,
                // so it should only be triggered when rendering indeed happend
                // in zrender. (Consider the case that dipatchAction is keep
                // triggering when mouse move).
                if (
                    // Although zr is dirty if initial animation is not finished
                    // and this checking is called on frame, we also check
                    // animation finished for robustness.
                    zr.animation.isFinished()
                    && !ecIns[PENDING_UPDATE]
                    && !ecIns._scheduler.unfinished
                    && !ecIns._pendingActions.length
                ) {
                    ecIns.trigger('finished');
                }
            });
        };

        bindMouseEvent = function (zr: zrender.ZRenderType, ecIns: ECharts): void {
            zr.on('mouseover', function (e) {
                const el = e.target;
                const dispatcher = findEventDispatcher(el, isHighDownDispatcher);
                if (dispatcher) {
                    handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api);
                    markStatusToUpdate(ecIns);
                }
            }).on('mouseout', function (e) {
                const el = e.target;
                const dispatcher = findEventDispatcher(el, isHighDownDispatcher);
                if (dispatcher) {
                    handleGlboalMouseOutForHighDown(dispatcher, e, ecIns._api);
                    markStatusToUpdate(ecIns);
                }
            }).on('click', function (e) {
                const el = e.target;
                const dispatcher = findEventDispatcher(
                    el, (target) => getECData(target).dataIndex != null, true
                );
                if (dispatcher) {
                    const actionType = (dispatcher as ECElement).selected ? 'unselect' : 'select';
                    const ecData = getECData(dispatcher);
                    ecIns._api.dispatchAction({
                        type: actionType,
                        dataType: ecData.dataType,
                        dataIndexInside: ecData.dataIndex,
                        seriesIndex: ecData.seriesIndex,
                        isFromClick: true
                    });
                }
            });
        };

        clearColorPalette = function (ecModel: GlobalModel): void {
            ecModel.clearColorPalette();
            ecModel.eachSeries(function (seriesModel) {
                seriesModel.clearColorPalette();
            });
        };

        render = (
            ecIns: ECharts, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload,
            updateParams: UpdateLifecycleParams
        ) => {

            renderComponents(ecIns, ecModel, api, payload, updateParams);

            each(ecIns._chartsViews, function (chart: ChartView) {
                chart.__alive = false;
            });

            renderSeries(ecIns, ecModel, api, payload, updateParams);

            // Remove groups of unrendered charts
            each(ecIns._chartsViews, function (chart: ChartView) {
                if (!chart.__alive) {
                    chart.remove(ecModel, api);
                }
            });
        };

        renderComponents = (
            ecIns: ECharts, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload,
            updateParams: UpdateLifecycleParams, dirtyList?: ComponentView[]
        ) => {
            each(dirtyList || ecIns._componentsViews, function (componentView: ComponentView) {
                const componentModel = componentView.__model;
                clearStates(componentModel, componentView);

                componentView.render(componentModel, ecModel, api, payload);

                updateZ(componentModel, componentView);

                updateStates(componentModel, componentView);
            });

        };

        /**
         * Render each chart and component
         */
        renderSeries = (
            ecIns: ECharts,
            ecModel: GlobalModel,
            api: ExtensionAPI,
            payload: Payload | 'remain',
            updateParams: UpdateLifecycleParams,
            dirtyMap?: {[uid: string]: any}
        ) => {
            // Render all charts
            const scheduler = ecIns._scheduler;

            updateParams = extend(updateParams || {}, {
                updatedSeries: ecModel.getSeries()
            });

            // TODO progressive?
            lifecycle.trigger('series:beforeupdate', ecModel, api, updateParams);

            let unfinished: boolean = false;
            ecModel.eachSeries(function (seriesModel) {
                const chartView = ecIns._chartsMap[seriesModel.__viewId];
                chartView.__alive = true;

                const renderTask = chartView.renderTask;
                scheduler.updatePayload(renderTask, payload);

                // TODO states on marker.
                clearStates(seriesModel, chartView);

                if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
                    renderTask.dirty();
                }
                if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
                    unfinished = true;
                }

                chartView.group.silent = !!seriesModel.get('silent');
                // Should not call markRedraw on group, because it will disable zrender
                // increamental render (alway render from the __startIndex each frame)
                // chartView.group.markRedraw();

                updateBlend(seriesModel, chartView);

                updateSeriesElementSelection(seriesModel);
            });

            scheduler.unfinished = unfinished || scheduler.unfinished;

            lifecycle.trigger('series:layoutlabels', ecModel, api, updateParams);

            // transition after label is layouted.
            lifecycle.trigger('series:transition', ecModel, api, updateParams);

            ecModel.eachSeries(function (seriesModel) {
                const chartView = ecIns._chartsMap[seriesModel.__viewId];
                // Update Z after labels updated. Before applying states.
                updateZ(seriesModel, chartView);

                // NOTE: Update states after label is updated.
                // label should be in normal status when layouting.
                updateStates(seriesModel, chartView);
            });

            // If use hover layer
            updateHoverLayerStatus(ecIns, ecModel);

            lifecycle.trigger('series:afterupdate', ecModel, api, updateParams);
        };

        markStatusToUpdate = function (ecIns: ECharts): void {
            ecIns[STATUS_NEEDS_UPDATE_KEY] = true;
            // Wake up zrender if it's sleep. Let it update states in the next frame.
            ecIns.getZr().wakeUp();
        };

        applyChangedStates = function (ecIns: ECharts): void {
            if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
                return;
            }

            ecIns.getZr().storage.traverse(function (el: ECElement) {
                // Not applied on removed elements, it may still in fading.
                if (graphic.isElementRemoved(el)) {
                    return;
                }
                applyElementStates(el);
            });

            ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
        };

        function applyElementStates(el: ECElement) {
            const newStates = [];

            const oldStates = el.currentStates;
            // Keep other states.
            for (let i = 0; i < oldStates.length; i++) {
                const stateName = oldStates[i];
                if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
                    newStates.push(stateName);
                }
            }

            // Only use states when it's exists.
            if (el.selected && el.states.select) {
                newStates.push('select');
            }
            if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
                newStates.push('emphasis');
            }
            else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
                newStates.push('blur');
            }
            el.useStates(newStates);
        }

        function updateHoverLayerStatus(ecIns: ECharts, ecModel: GlobalModel): void {
            const zr = ecIns._zr;
            const storage = zr.storage;
            let elCount = 0;

            storage.traverse(function (el) {
                if (!el.isGroup) {
                    elCount++;
                }
            });

            if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) {
                ecModel.eachSeries(function (seriesModel) {
                    if (seriesModel.preventUsingHoverLayer) {
                        return;
                    }
                    const chartView = ecIns._chartsMap[seriesModel.__viewId];
                    if (chartView.__alive) {
                        chartView.group.traverse(function (el: ECElement) {
                            if (el.states.emphasis) {
                                el.states.emphasis.hoverLayer = true;
                            }
                        });
                    }
                });
            }
        };

        /**
         * Update chart and blend.
         */
        function updateBlend(seriesModel: SeriesModel, chartView: ChartView): void {
            const blendMode = seriesModel.get('blendMode') || null;
            if (__DEV__) {
                if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
                    console.warn('Only canvas support blendMode');
                }
            }
            chartView.group.traverse(function (el: Displayable) {
                // FIXME marker and other components
                if (!el.isGroup) {
                    // DONT mark the element dirty. In case element is incremental and don't wan't to rerender.
                    el.style.blend = blendMode;
                }
                if ((el as IncrementalDisplayable).eachPendingDisplayable) {
                    (el as IncrementalDisplayable).eachPendingDisplayable(function (displayable) {
                        displayable.style.blend = blendMode;
                    });
                }
            });
        };

        function updateZ(model: ComponentModel, view: ComponentView | ChartView): void {
            if (model.preventAutoZ) {
                return;
            }
            // Set z and zlevel
            _updateZ(
                view.group,
                model.get('z') || 0,
                model.get('zlevel') || 0,
                -Infinity
            );
        };

        function _updateZ(el: Element, z: number, zlevel: number, maxZ2: number): number {
            // Group may also have textContent
            const label = el.getTextContent();
            const labelLine = el.getTextGuideLine();
            const isGroup = el.isGroup;

            if (isGroup) {
                // set z & zlevel of children elements of Group
                // el.traverse((childEl: Element) => _updateZ(childEl, z, zlevel));
                const children = (el as graphic.Group).childrenRef();
                for (let i = 0; i < children.length; i++) {
                    maxZ2 = Math.max(_updateZ(children[i], z, zlevel, maxZ2), maxZ2);
                }
            }
            else {
                // not Group
                (el as Displayable).z = z;
                (el as Displayable).zlevel = zlevel;

                maxZ2 = Math.max((el as Displayable).z2, maxZ2);
            }

            // always set z and zlevel if label/labelLine exists
            if (label) {
                label.z = z;
                label.zlevel = zlevel;
                // lift z2 of text content
                // TODO if el.emphasis.z2 is spcefied, what about textContent.
                isFinite(maxZ2) && (label.z2 = maxZ2 + 2);
            }
            if (labelLine) {
                const textGuideLineConfig = el.textGuideLineConfig;
                labelLine.z = z;
                labelLine.zlevel = zlevel;
                isFinite(maxZ2)
                    && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1));
            }
            return maxZ2;
        }

        // Clear states without animation.
        // TODO States on component.
        function clearStates(model: ComponentModel, view: ComponentView | ChartView): void {
            view.group.traverse(function (el: Displayable) {
                // Not applied on removed elements, it may still in fading.
                if (graphic.isElementRemoved(el)) {
                    return;
                }

                const textContent = el.getTextContent();
                const textGuide = el.getTextGuideLine();
                if (el.stateTransition) {
                    el.stateTransition = null;
                }
                if (textContent && textContent.stateTransition) {
                    textContent.stateTransition = null;
                }
                if (textGuide && textGuide.stateTransition) {
                    textGuide.stateTransition = null;
                }

                // TODO If el is incremental.
                if (el.hasState()) {
                    el.prevStates = el.currentStates;
                    el.clearStates();
                }
                else if (el.prevStates) {
                    el.prevStates = null;
                }
            });
        }

        function updateStates(model: ComponentModel, view: ComponentView | ChartView): void {
            const stateAnimationModel = (model as SeriesModel).getModel('stateAnimation');
            const enableAnimation = model.isAnimationEnabled();
            const duration = stateAnimationModel.get('duration');
            const stateTransition = duration > 0 ? {
                duration,
                delay: stateAnimationModel.get('delay'),
                easing: stateAnimationModel.get('easing')
                // additive: stateAnimationModel.get('additive')
            } : null;
            view.group.traverse(function (el: Displayable) {
                if (el.states && el.states.emphasis) {
                    // Not applied on removed elements, it may still in fading.
                    if (graphic.isElementRemoved(el)) {
                        return;
                    }

                    if (el instanceof graphic.Path) {
                        savePathStates(el);
                    }

                    // Only updated on changed element. In case element is incremental and don't wan't to rerender.
                    // TODO, a more proper way?
                    if (el.__dirty) {
                        const prevStates = el.prevStates;
                        // Restore states without animation
                        if (prevStates) {
                            el.useStates(prevStates);
                        }
                    }

                    // Update state transition and enable animation again.
                    if (enableAnimation) {
                        el.stateTransition = stateTransition;
                        const textContent = el.getTextContent();
                        const textGuide = el.getTextGuideLine();
                        // TODO Is it necessary to animate label?
                        if (textContent) {
                            textContent.stateTransition = stateTransition;
                        }
                        if (textGuide) {
                            textGuide.stateTransition = stateTransition;
                        }
                    }

                    // The use higlighted and selected flag to toggle states.
                    if (el.__dirty) {
                        applyElementStates(el);
                    }
                }
            });
        };

        createExtensionAPI = function (ecIns: ECharts): ExtensionAPI {
            return new (class extends ExtensionAPI {
                getCoordinateSystems(): CoordinateSystemMaster[] {
                    return ecIns._coordSysMgr.getCoordinateSystems();
                }
                getComponentByElement(el: Element) {
                    while (el) {
                        const modelInfo = (el as ViewRootGroup).__ecComponentInfo;
                        if (modelInfo != null) {
                            return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
                        }
                        el = el.parent;
                    }
                }
                enterEmphasis(el: Element, highlightDigit?: number) {
                    enterEmphasis(el, highlightDigit);
                    markStatusToUpdate(ecIns);
                }
                leaveEmphasis(el: Element, highlightDigit?: number) {
                    leaveEmphasis(el, highlightDigit);
                    markStatusToUpdate(ecIns);
                }
                enterBlur(el: Element) {
                    enterBlur(el);
                    markStatusToUpdate(ecIns);
                }
                leaveBlur(el: Element) {
                    leaveBlur(el);
                    markStatusToUpdate(ecIns);
                }
                enterSelect(el: Element) {
                    enterSelect(el);
                    markStatusToUpdate(ecIns);
                }
                leaveSelect(el: Element) {
                    leaveSelect(el);
                    markStatusToUpdate(ecIns);
                }
                getModel(): GlobalModel {
                    return ecIns.getModel();
                }
                getViewOfComponentModel(componentModel: ComponentModel): ComponentView {
                    return ecIns.getViewOfComponentModel(componentModel);
                }
                getViewOfSeriesModel(seriesModel: SeriesModel): ChartView {
                    return ecIns.getViewOfSeriesModel(seriesModel);
                }
            })(ecIns);
        };

        enableConnect = function (chart: ECharts): void {

            function updateConnectedChartsStatus(charts: ECharts[], status: ConnectStatus) {
                for (let i = 0; i < charts.length; i++) {
                    const otherChart = charts[i];
                    otherChart[CONNECT_STATUS_KEY] = status;
                }
            }

            each(eventActionMap, function (actionType, eventType) {
                chart._messageCenter.on(eventType, function (event: ECActionEvent) {
                    if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
                        if (event && event.escapeConnect) {
                            return;
                        }

                        const action = chart.makeActionFromEvent(event);
                        const otherCharts: ECharts[] = [];

                        each(instances, function (otherChart) {
                            if (otherChart !== chart && otherChart.group === chart.group) {
                                otherCharts.push(otherChart);
                            }
                        });

                        updateConnectedChartsStatus(otherCharts, CONNECT_STATUS_PENDING);
                        each(otherCharts, function (otherChart) {
                            if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
                                otherChart.dispatchAction(action);
                            }
                        });
                        updateConnectedChartsStatus(otherCharts, CONNECT_STATUS_UPDATED);
                    }
                });
            });
        };
    })();
}


const echartsProto = ECharts.prototype;
echartsProto.on = createRegisterEventWithLowercaseECharts('on');
echartsProto.off = createRegisterEventWithLowercaseECharts('off');
/**
 * @deprecated
 */
// @ts-ignore
echartsProto.one = function (eventName: string, cb: Function, ctx?: any) {
    const self = this;
    deprecateLog('ECharts#one is deprecated.');
    function wrapped(this: unknown, ...args2: any) {
        cb && cb.apply && cb.apply(this, args2);
        // @ts-ignore
        self.off(eventName, wrapped);
    };
    // @ts-ignore
    this.on.call(this, eventName, wrapped, ctx);
};

// /**
//  * Encode visual infomation from data after data processing
//  *
//  * @param {module:echarts/model/Global} ecModel
//  * @param {object} layout
//  * @param {boolean} [layoutFilter] `true`: only layout,
//  *                                 `false`: only not layout,
//  *                                 `null`/`undefined`: all.
//  * @param {string} taskBaseTag
//  * @private
//  */
// function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {
//     each(visualFuncs, function (visual, index) {
//         let isLayout = visual.isLayout;
//         if (layoutFilter == null
//             || (layoutFilter === false && !isLayout)
//             || (layoutFilter === true && isLayout)
//         ) {
//             visual.func(ecModel, api, payload);
//         }
//     });
// }


const MOUSE_EVENT_NAMES: ZRElementEventName[] = [
    'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove',
    'mousedown', 'mouseup', 'globalout', 'contextmenu'
];

function disposedWarning(id: string): void {
    if (__DEV__) {
        console.warn('Instance ' + id + ' has been disposed');
    }
}


const actions: {
    [actionType: string]: {
        action: ActionHandler,
        actionInfo: ActionInfo
    }
} = {};

/**
 * Map eventType to actionType
 */
const eventActionMap: {[eventType: string]: string} = {};

const dataProcessorFuncs: StageHandlerInternal[] = [];

const optionPreprocessorFuncs: OptionPreprocessor[] = [];

const visualFuncs: StageHandlerInternal[] = [];

const themeStorage: {[themeName: string]: ThemeOption} = {};

const loadingEffects: {[effectName: string]: LoadingEffectCreator} = {};

const instances: {[id: string]: ECharts} = {};
const connectedGroups: {[groupId: string]: boolean} = {};

let idBase: number = +(new Date()) - 0;
let groupIdBase: number = +(new Date()) - 0;
const DOM_ATTRIBUTE_KEY = '_echarts_instance_';


/**
 * @param opts.devicePixelRatio Use window.devicePixelRatio by default
 * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart.
 * @param opts.width Use clientWidth of the input `dom` by default.
 *        Can be 'auto' (the same as null/undefined)
 * @param opts.height Use clientHeight of the input `dom` by default.
 *        Can be 'auto' (the same as null/undefined)
 * @param opts.locale Specify the locale.
 * @param opts.useDirtyRect Enable dirty rectangle rendering or not.
 */
export function init(
    dom: HTMLElement,
    theme?: string | object,
    opts?: EChartsInitOpts
): EChartsType {
    if (__DEV__) {
        if (!dom) {
            throw new Error('Initialize failed: invalid dom.');
        }
    }

    const existInstance = getInstanceByDom(dom);
    if (existInstance) {
        if (__DEV__) {
            console.warn('There is a chart instance already initialized on the dom.');
        }
        return existInstance;
    }

    if (__DEV__) {
        if (isDom(dom)
            && dom.nodeName.toUpperCase() !== 'CANVAS'
            && (
                (!dom.clientWidth && (!opts || opts.width == null))
                || (!dom.clientHeight && (!opts || opts.height == null))
            )
        ) {
            console.warn('Can\'t get DOM width or height. Please check '
            + 'dom.clientWidth and dom.clientHeight. They should not be 0.'
            + 'For example, you may need to call this in the callback '
            + 'of window.onload.');
        }
    }

    const chart = new ECharts(dom, theme, opts);
    chart.id = 'ec_' + idBase++;
    instances[chart.id] = chart;

    modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);

    enableConnect(chart);

    lifecycle.trigger('afterinit', chart);

    return chart;
}

/**
 * @usage
 * (A)
 * ```js
 * let chart1 = echarts.init(dom1);
 * let chart2 = echarts.init(dom2);
 * chart1.group = 'xxx';
 * chart2.group = 'xxx';
 * echarts.connect('xxx');
 * ```
 * (B)
 * ```js
 * let chart1 = echarts.init(dom1);
 * let chart2 = echarts.init(dom2);
 * echarts.connect('xxx', [chart1, chart2]);
 * ```
 */
export function connect(groupId: string | EChartsType[]): string {
    // Is array of charts
    if (isArray(groupId)) {
        const charts = groupId;
        groupId = null;
        // If any chart has group
        each(charts, function (chart) {
            if (chart.group != null) {
                groupId = chart.group;
            }
        });
        groupId = groupId || ('g_' + groupIdBase++);
        each(charts, function (chart) {
            chart.group = groupId as string;
        });
    }
    connectedGroups[groupId as string] = true;
    return groupId as string;
}

/**
 * @deprecated
 */
export function disConnect(groupId: string): void {
    connectedGroups[groupId] = false;
}

/**
 * Alias and backword compat
 */
export const disconnect = disConnect;

/**
 * Dispose a chart instance
 */
export function dispose(chart: EChartsType | HTMLElement | string): void {
    if (typeof chart === 'string') {
        chart = instances[chart];
    }
    else if (!(chart instanceof ECharts)) {
        // Try to treat as dom
        chart = getInstanceByDom(chart);
    }
    if ((chart instanceof ECharts) && !chart.isDisposed()) {
        chart.dispose();
    }
}

export function getInstanceByDom(dom: HTMLElement): EChartsType {
    return instances[modelUtil.getAttribute(dom, DOM_ATTRIBUTE_KEY)];
}

export function getInstanceById(key: string): EChartsType {
    return instances[key];
}

/**
 * Register theme
 */
export function registerTheme(name: string, theme: ThemeOption): void {
    themeStorage[name] = theme;
}

/**
 * Register option preprocessor
 */
export function registerPreprocessor(preprocessorFunc: OptionPreprocessor): void {
    if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) {
        optionPreprocessorFuncs.push(preprocessorFunc);
    }
}

export function registerProcessor(
    priority: number | StageHandler | StageHandlerOverallReset,
    processor?: StageHandler | StageHandlerOverallReset
): void {
    normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
}


/**
 * Register postIniter
 * @param {Function} postInitFunc
 */
export function registerPostInit(postInitFunc: PostIniter): void {
    registerUpdateLifecycle('afterinit', postInitFunc);
}

/**
 * Register postUpdater
 * @param {Function} postUpdateFunc
 */
export function registerPostUpdate(postUpdateFunc: PostUpdater): void {
    registerUpdateLifecycle('afterupdate', postUpdateFunc);
}

export function registerUpdateLifecycle<T extends keyof LifecycleEvents>(
    name: T, cb: (...args: LifecycleEvents[T]) => void
): void {
    (lifecycle as any).on(name, cb);
}

/**
 * @usage
 * registerAction('someAction', 'someEvent', function () { ... });
 * registerAction('someAction', function () { ... });
 * registerAction(
 *     {type: 'someAction', event: 'someEvent', update: 'updateView'},
 *     function () { ... }
 * );
 *
 * @param {(string|Object)} actionInfo
 * @param {string} actionInfo.type
 * @param {string} [actionInfo.event]
 * @param {string} [actionInfo.update]
 * @param {string} [eventName]
 * @param {Function} action
 */
export function registerAction(type: string, eventName: string, action: ActionHandler): void;
export function registerAction(type: string, action: ActionHandler): void;
export function registerAction(actionInfo: ActionInfo, action: ActionHandler): void;
export function registerAction(
    actionInfo: string | ActionInfo,
    eventName: string | ActionHandler,
    action?: ActionHandler
): void {
    if (typeof eventName === 'function') {
        action = eventName;
        eventName = '';
    }
    const actionType = isObject(actionInfo)
        ? (actionInfo as ActionInfo).type
        : ([actionInfo, actionInfo = {
            event: eventName
        } as ActionInfo][0]);

    // Event name is all lowercase
    (actionInfo as ActionInfo).event = (
        (actionInfo as ActionInfo).event || actionType as string
    ).toLowerCase();
    eventName = (actionInfo as ActionInfo).event;

    if (eventActionMap[eventName as string]) {
        // Already registered.
        return;
    }

    // Validate action type and event name.
    assert(ACTION_REG.test(actionType as string) && ACTION_REG.test(eventName));

    if (!actions[actionType as string]) {
        actions[actionType as string] = {action: action, actionInfo: actionInfo as ActionInfo};
    }
    eventActionMap[eventName as string] = actionType as string;
}

export function registerCoordinateSystem(
    type: string,
    coordSysCreator: CoordinateSystemCreator
): void {
    CoordinateSystemManager.register(type, coordSysCreator);
}

/**
 * Get dimensions of specified coordinate system.
 * @param {string} type
 * @return {Array.<string|Object>}
 */
export function getCoordinateSystemDimensions(type: string): DimensionDefinitionLoose[] {
    const coordSysCreator = CoordinateSystemManager.get(type);
    if (coordSysCreator) {
        return coordSysCreator.getDimensionsInfo
            ? coordSysCreator.getDimensionsInfo()
            : coordSysCreator.dimensions.slice();
    }
}

export {registerLocale} from './locale';

/**
 * Layout is a special stage of visual encoding
 * Most visual encoding like color are common for different chart
 * But each chart has it's own layout algorithm
 */
function registerLayout(priority: number, layoutTask: StageHandler | StageHandlerOverallReset): void;
function registerLayout(layoutTask: StageHandler | StageHandlerOverallReset): void;
function registerLayout(
    priority: number | StageHandler | StageHandlerOverallReset,
    layoutTask?: StageHandler | StageHandlerOverallReset
): void {
    normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
}

function registerVisual(priority: number, layoutTask: StageHandler | StageHandlerOverallReset): void;
function registerVisual(layoutTask: StageHandler | StageHandlerOverallReset): void;
function registerVisual(
    priority: number | StageHandler | StageHandlerOverallReset,
    visualTask?: StageHandler | StageHandlerOverallReset
): void {
    normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
}

export {registerLayout, registerVisual};

const registeredTasks: (StageHandler | StageHandlerOverallReset)[] = [];

function normalizeRegister(
    targetList: StageHandler[],
    priority: number | StageHandler | StageHandlerOverallReset,
    fn: StageHandler | StageHandlerOverallReset,
    defaultPriority: number,
    visualType?: StageHandlerInternal['visualType']
): void {
    if (isFunction(priority) || isObject(priority)) {
        fn = priority as (StageHandler | StageHandlerOverallReset);
        priority = defaultPriority;
    }

    if (__DEV__) {
        if (isNaN(priority) || priority == null) {
            throw new Error('Illegal priority');
        }
        // Check duplicate
        each(targetList, function (wrap) {
            assert((wrap as StageHandlerInternal).__raw !== fn);
        });
    }

    // Already registered
    if (indexOf(registeredTasks, fn) >= 0) {
        return;
    }
    registeredTasks.push(fn);

    const stageHandler = Scheduler.wrapStageHandler(fn, visualType);

    stageHandler.__prio = priority;
    stageHandler.__raw = fn;
    targetList.push(stageHandler);
}

export function registerLoading(
    name: string,
    loadingFx: LoadingEffectCreator
): void {
    loadingEffects[name] = loadingFx;
}

/**
 * ZRender need a canvas context to do measureText.
 * But in node environment canvas may be created by node-canvas.
 * So we need to specify how to create a canvas instead of using document.createElement('canvas')
 *
 * Be careful of using it in the browser.
 *
 * @example
 *     let Canvas = require('canvas');
 *     let echarts = require('echarts');
 *     echarts.setCanvasCreator(function () {
 *         // Small size is enough.
 *         return new Canvas(32, 32);
 *     });
 */
export function setCanvasCreator(creator: () => HTMLCanvasElement): void {
    $override('createCanvas', creator);
}

/**
 * The parameters and usage: see `geoSourceManager.registerMap`.
 * Compatible with previous `echarts.registerMap`.
 */
export function registerMap(
    mapName: Parameters<typeof geoSourceManager.registerMap>[0],
    geoJson: Parameters<typeof geoSourceManager.registerMap>[1],
    specialAreas?: Parameters<typeof geoSourceManager.registerMap>[2]
): void {
    geoSourceManager.registerMap(mapName, geoJson, specialAreas);
}

export function getMap(mapName: string) {
    return geoSourceManager.getMapForUser(mapName);
}

export const registerTransform = registerExternalTransform;

/**
 * Globa dispatchAction to a specified chart instance.
 */
// export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters<ECharts['dispatchAction']>[1]) {
//     if (!payload || !payload.chartId) {
//         // Must have chartId to find chart
//         return;
//     }
//     const chart = instances[payload.chartId];
//     if (chart) {
//         chart.dispatchAction(payload, opt);
//     }
// }



// Buitlin global visual
registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask);

registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask);
registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask);

registerVisual(PRIORITY_VISUAL_DECAL, decal);

registerPreprocessor(backwardCompat);
registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
registerLoading('default', loadingDefault);

// Default actions

registerAction({
    type: HIGHLIGHT_ACTION_TYPE,
    event: HIGHLIGHT_ACTION_TYPE,
    update: HIGHLIGHT_ACTION_TYPE
}, noop);

registerAction({
    type: DOWNPLAY_ACTION_TYPE,
    event: DOWNPLAY_ACTION_TYPE,
    update: DOWNPLAY_ACTION_TYPE
}, noop);

registerAction({
    type: SELECT_ACTION_TYPE,
    event: SELECT_ACTION_TYPE,
    update: SELECT_ACTION_TYPE
}, noop);

registerAction({
    type: UNSELECT_ACTION_TYPE,
    event: UNSELECT_ACTION_TYPE,
    update: UNSELECT_ACTION_TYPE
}, noop);

registerAction({
    type: TOGGLE_SELECT_ACTION_TYPE,
    event: TOGGLE_SELECT_ACTION_TYPE,
    update: TOGGLE_SELECT_ACTION_TYPE
}, noop);

// Default theme
registerTheme('light', lightTheme);
registerTheme('dark', darkTheme);

// For backward compatibility, where the namespace `dataTool` will
// be mounted on `echarts` is the extension `dataTool` is imported.
export const dataTool = {};

export interface EChartsType extends ECharts {}
