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

import {bind, each, indexOf, curry, extend, retrieve, normalizeCssArray, isFunction} from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import {getECData} from '../../util/innerStore';
import {
    isHighDownDispatcher,
    setAsHighDownDispatcher,
    setDefaultStateProxy,
    enableHoverFocus
} from '../../util/states';
import DataDiffer from '../../data/DataDiffer';
import * as helper from '../helper/treeHelper';
import Breadcrumb from './Breadcrumb';
import RoamController, { RoamEventParams } from '../../component/helper/RoamController';
import BoundingRect, { RectLike } from 'zrender/src/core/BoundingRect';
import * as matrix from 'zrender/src/core/matrix';
import * as animationUtil from '../../util/animation';
import makeStyleMapper from '../../model/mixin/makeStyleMapper';
import ChartView from '../../view/Chart';
import Tree, { TreeNode } from '../../data/Tree';
import TreemapSeriesModel, { TreemapSeriesNodeItemOption } from './TreemapSeries';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import Model from '../../model/Model';
import { LayoutRect } from '../../util/layout';
import { TreemapLayoutNode } from './treemapLayout';
import Element from 'zrender/src/Element';
import Displayable from 'zrender/src/graphic/Displayable';
import { makeInner, convertOptionIdName } from '../../util/model';
import { PathStyleProps, PathProps } from 'zrender/src/graphic/Path';
import { TreeSeriesNodeItemOption } from '../tree/TreeSeries';
import {
    TreemapRootToNodePayload,
    TreemapMovePayload,
    TreemapRenderPayload,
    TreemapZoomToNodePayload
} from './treemapAction';
import { ColorString, ECElement } from '../../util/types';
import { windowOpen } from '../../util/format';
import { TextStyleProps } from 'zrender/src/graphic/Text';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';

const Group = graphic.Group;
const Rect = graphic.Rect;

const DRAG_THRESHOLD = 3;
const PATH_LABEL_NOAMAL = 'label';
const PATH_UPPERLABEL_NORMAL = 'upperLabel';
const Z_BASE = 10; // Should bigger than every z.
const Z_BG = 1;
const Z_CONTENT = 2;

const getStateItemStyle = makeStyleMapper([
    ['fill', 'color'],
    // `borderColor` and `borderWidth` has been occupied,
    // so use `stroke` to indicate the stroke of the rect.
    ['stroke', 'strokeColor'],
    ['lineWidth', 'strokeWidth'],
    ['shadowBlur'],
    ['shadowOffsetX'],
    ['shadowOffsetY'],
    ['shadowColor']
    // Option decal is in `DecalObject` but style.decal is in `PatternObject`.
    // So do not transfer decal directly.
]);
const getItemStyleNormal = function (model: Model<TreemapSeriesNodeItemOption['itemStyle']>): PathStyleProps {
    // Normal style props should include emphasis style props.
    const itemStyle = getStateItemStyle(model) as PathStyleProps;
    // Clear styles set by emphasis.
    itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null;
    return itemStyle;
};

interface RenderElementStorage {
    nodeGroup: graphic.Group[]
    background: graphic.Rect[]
    content: graphic.Rect[]
}

type LastCfgStorage = {
    [key in keyof RenderElementStorage]: LastCfg[]
    // nodeGroup: {
    //     old: Pick<graphic.Group, 'position'>[]
    //     fadein: boolean
    // }[]
    // background: {
    //     old: Pick<graphic.Rect, 'shape'>
    //     fadein: boolean
    // }[]
    // content: {
    //     old: Pick<graphic.Rect, 'shape'>
    //     fadein: boolean
    // }[]
};

interface FoundTargetInfo {
    node: TreeNode

    offsetX?: number
    offsetY?: number
}

interface RenderResult {
    lastsForAnimation: LastCfgStorage
    willInvisibleEls?: graphic.Rect[]
    willDeleteEls: RenderElementStorage
    renderFinally: () => void
}

interface ReRoot {
    rootNodeGroup: graphic.Group
    direction: 'drillDown' | 'rollUp'
}

interface LastCfg {
    oldX?: number
    oldY?: number
    oldShape?: graphic.Rect['shape']
    fadein: boolean
}

const inner = makeInner<{
    nodeWidth: number
    nodeHeight: number
    willDelete: boolean
}, Element>();

class TreemapView extends ChartView {

    static type = 'treemap';
    type = TreemapView.type;

    private _containerGroup: graphic.Group;
    private _breadcrumb: Breadcrumb;
    private _controller: RoamController;

    private _oldTree: Tree;

    private _state: 'ready' | 'animating' = 'ready';

    private _storage = createStorage() as RenderElementStorage;

    seriesModel: TreemapSeriesModel;
    api: ExtensionAPI;
    ecModel: GlobalModel;

    /**
     * @override
     */
    render(
        seriesModel: TreemapSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: TreemapZoomToNodePayload | TreemapRenderPayload | TreemapMovePayload | TreemapRootToNodePayload
    ) {

        const models = ecModel.findComponents({
            mainType: 'series', subType: 'treemap', query: payload
        });
        if (indexOf(models, seriesModel) < 0) {
            return;
        }

        this.seriesModel = seriesModel;
        this.api = api;
        this.ecModel = ecModel;

        const types = ['treemapZoomToNode', 'treemapRootToNode'];
        const targetInfo = helper
            .retrieveTargetInfo(payload, types, seriesModel);
        const payloadType = payload && payload.type;
        const layoutInfo = seriesModel.layoutInfo;
        const isInit = !this._oldTree;
        const thisStorage = this._storage;

        // Mark new root when action is treemapRootToNode.
        const reRoot = (payloadType === 'treemapRootToNode' && targetInfo && thisStorage)
            ? {
                rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()],
                direction: (payload as TreemapRootToNodePayload).direction
            }
            : null;

        const containerGroup = this._giveContainerGroup(layoutInfo);

        const renderResult = this._doRender(containerGroup, seriesModel, reRoot);
        (
            !isInit && (
                !payloadType
                || payloadType === 'treemapZoomToNode'
                || payloadType === 'treemapRootToNode'
            )
        )
            ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot)
            : renderResult.renderFinally();

        this._resetController(api);

        this._renderBreadcrumb(seriesModel, api, targetInfo);
    }

    private _giveContainerGroup(layoutInfo: LayoutRect) {
        let containerGroup = this._containerGroup;
        if (!containerGroup) {
            // FIXME
            // 加一层containerGroup是为了clip，但是现在clip功能并没有实现。
            containerGroup = this._containerGroup = new Group();
            this._initEvents(containerGroup);
            this.group.add(containerGroup);
        }
        containerGroup.x = layoutInfo.x;
        containerGroup.y = layoutInfo.y;

        return containerGroup;
    }

    private _doRender(containerGroup: graphic.Group, seriesModel: TreemapSeriesModel, reRoot: ReRoot): RenderResult {
        const thisTree = seriesModel.getData().tree;
        const oldTree = this._oldTree;

        // Clear last shape records.
        const lastsForAnimation = createStorage() as LastCfgStorage;
        const thisStorage = createStorage() as RenderElementStorage;
        const oldStorage = this._storage;
        const willInvisibleEls: RenderResult['willInvisibleEls'] = [];

        function doRenderNode(thisNode: TreeNode, oldNode: TreeNode, parentGroup: graphic.Group, depth: number) {
            return renderNode(
                seriesModel,
                thisStorage, oldStorage, reRoot,
                lastsForAnimation, willInvisibleEls,
                thisNode, oldNode, parentGroup, depth
            );
        }

        // Notice: when thisTree and oldTree are the same tree (see list.cloneShallow),
        // the oldTree is actually losted, so we can not find all of the old graphic
        // elements from tree. So we use this stragegy: make element storage, move
        // from old storage to new storage, clear old storage.

        dualTravel(
            thisTree.root ? [thisTree.root] : [],
            (oldTree && oldTree.root) ? [oldTree.root] : [],
            containerGroup,
            thisTree === oldTree || !oldTree,
            0
        );

        // Process all removing.
        const willDeleteEls = clearStorage(oldStorage) as RenderElementStorage;

        this._oldTree = thisTree;
        this._storage = thisStorage;

        return {
            lastsForAnimation,
            willDeleteEls,
            renderFinally
        };

        function dualTravel(
            thisViewChildren: TreemapLayoutNode[],
            oldViewChildren: TreemapLayoutNode[],
            parentGroup: graphic.Group,
            sameTree: boolean,
            depth: number
        ) {
            // When 'render' is triggered by action,
            // 'this' and 'old' may be the same tree,
            // we use rawIndex in that case.
            if (sameTree) {
                oldViewChildren = thisViewChildren;
                each(thisViewChildren, function (child, index) {
                    !child.isRemoved() && processNode(index, index);
                });
            }
            // Diff hierarchically (diff only in each subtree, but not whole).
            // because, consistency of view is important.
            else {
                (new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey))
                    .add(processNode)
                    .update(processNode)
                    .remove(curry(processNode, null))
                    .execute();
            }

            function getKey(node: TreeNode) {
                // Identify by name or raw index.
                return node.getId();
            }

            function processNode(newIndex: number, oldIndex?: number) {
                const thisNode = newIndex != null ? thisViewChildren[newIndex] : null;
                const oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null;

                const group = doRenderNode(thisNode, oldNode, parentGroup, depth);

                group && dualTravel(
                    thisNode && thisNode.viewChildren || [],
                    oldNode && oldNode.viewChildren || [],
                    group,
                    sameTree,
                    depth + 1
                );
            }
        }

        function clearStorage(storage: RenderElementStorage) {
            const willDeleteEls = createStorage() as RenderElementStorage;
            storage && each(storage, function (store, storageName) {
                const delEls = willDeleteEls[storageName];
                each(store, function (el) {
                    el && (delEls.push(el as any), inner(el).willDelete = true);
                });
            });
            return willDeleteEls;
        }

        function renderFinally() {
            each(willDeleteEls, function (els) {
                each(els, function (el) {
                    el.parent && el.parent.remove(el);
                });
            });
            each(willInvisibleEls, function (el) {
                el.invisible = true;
                // Setting invisible is for optimizing, so no need to set dirty,
                // just mark as invisible.
                el.dirty();
            });
        }
    }

    private _doAnimation(
        containerGroup: graphic.Group,
        renderResult: RenderResult,
        seriesModel: TreemapSeriesModel,
        reRoot: ReRoot
    ) {
        if (!seriesModel.get('animation')) {
            return;
        }

        const durationOption = seriesModel.get('animationDurationUpdate');
        const easingOption = seriesModel.get('animationEasing');
        // TODO: do not support function until necessary.
        const duration = (isFunction(durationOption) ? 0 : durationOption) || 0;
        const easing = (isFunction(easingOption) ? null : easingOption) || 'cubicOut';
        const animationWrap = animationUtil.createWrap();

        // Make delete animations.
        each(renderResult.willDeleteEls, function (store, storageName) {
            each(store, function (el, rawIndex) {
                if ((el as Displayable).invisible) {
                    return;
                }

                const parent = el.parent; // Always has parent, and parent is nodeGroup.
                let target: PathProps;
                const innerStore = inner(parent);

                if (reRoot && reRoot.direction === 'drillDown') {
                    target = parent === reRoot.rootNodeGroup
                        // This is the content element of view root.
                        // Only `content` will enter this branch, because
                        // `background` and `nodeGroup` will not be deleted.
                        ? {
                            shape: {
                                x: 0,
                                y: 0,
                                width: innerStore.nodeWidth,
                                height: innerStore.nodeHeight
                            },
                            style: {
                                opacity: 0
                            }
                        }
                        // Others.
                        : {style: {opacity: 0}};
                }
                else {
                    let targetX = 0;
                    let targetY = 0;

                    if (!innerStore.willDelete) {
                        // Let node animate to right-bottom corner, cooperating with fadeout,
                        // which is appropriate for user understanding.
                        // Divided by 2 for reRoot rolling up effect.
                        targetX = innerStore.nodeWidth / 2;
                        targetY = innerStore.nodeHeight / 2;
                    }

                    target = storageName === 'nodeGroup'
                        ? {x: targetX, y: targetY, style: {opacity: 0}}
                        : {
                            shape: {x: targetX, y: targetY, width: 0, height: 0},
                            style: {opacity: 0}
                        };
                }

                // TODO: do not support delay until necessary.
                target && animationWrap.add(el, target, duration, 0, easing);
            });
        });

        // Make other animations
        each(this._storage, function (store, storageName) {
            each(store, function (el, rawIndex) {
                const last = renderResult.lastsForAnimation[storageName][rawIndex];
                const target: PathProps = {};

                if (!last) {
                    return;
                }

                if (el instanceof graphic.Group) {
                    if (last.oldX != null) {
                        target.x = el.x;
                        target.y = el.y;
                        el.x = last.oldX;
                        el.y = last.oldY;
                    }
                }
                else {
                    if (last.oldShape) {
                        target.shape = extend({}, el.shape);
                        el.setShape(last.oldShape);
                    }

                    if (last.fadein) {
                        el.setStyle('opacity', 0);
                        target.style = {opacity: 1};
                    }
                    // When animation is stopped for succedent animation starting,
                    // el.style.opacity might not be 1
                    else if (el.style.opacity !== 1) {
                        target.style = {opacity: 1};
                    }
                }

                animationWrap.add(el, target, duration, 0, easing);
            });
        }, this);

        this._state = 'animating';

        animationWrap
            .finished(bind(function () {
                this._state = 'ready';
                renderResult.renderFinally();
            }, this))
            .start();
    }

    private _resetController(api: ExtensionAPI) {
        let controller = this._controller;

        // Init controller.
        if (!controller) {
            controller = this._controller = new RoamController(api.getZr());
            controller.enable(this.seriesModel.get('roam'));
            controller.on('pan', bind(this._onPan, this));
            controller.on('zoom', bind(this._onZoom, this));
        }

        const rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight());
        controller.setPointerChecker(function (e, x, y) {
            return rect.contain(x, y);
        });
    }

    private _clearController() {
        let controller = this._controller;
        if (controller) {
            controller.dispose();
            controller = null;
        }
    }

    private _onPan(e: RoamEventParams['pan']) {
        if (this._state !== 'animating'
            && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)
        ) {
            // These param must not be cached.
            const root = this.seriesModel.getData().tree.root;

            if (!root) {
                return;
            }

            const rootLayout = root.getLayout();

            if (!rootLayout) {
                return;
            }

            this.api.dispatchAction({
                type: 'treemapMove',
                from: this.uid,
                seriesId: this.seriesModel.id,
                rootRect: {
                    x: rootLayout.x + e.dx, y: rootLayout.y + e.dy,
                    width: rootLayout.width, height: rootLayout.height
                }
            } as TreemapMovePayload);
        }
    }

    private _onZoom(e: RoamEventParams['zoom']) {
        let mouseX = e.originX;
        let mouseY = e.originY;

        if (this._state !== 'animating') {
            // These param must not be cached.
            const root = this.seriesModel.getData().tree.root;

            if (!root) {
                return;
            }

            const rootLayout = root.getLayout();

            if (!rootLayout) {
                return;
            }

            const rect = new BoundingRect(
                rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height
            );
            const layoutInfo = this.seriesModel.layoutInfo;

            // Transform mouse coord from global to containerGroup.
            mouseX -= layoutInfo.x;
            mouseY -= layoutInfo.y;

            // Scale root bounding rect.
            const m = matrix.create();
            matrix.translate(m, m, [-mouseX, -mouseY]);
            matrix.scale(m, m, [e.scale, e.scale]);
            matrix.translate(m, m, [mouseX, mouseY]);

            rect.applyTransform(m);

            this.api.dispatchAction({
                type: 'treemapRender',
                from: this.uid,
                seriesId: this.seriesModel.id,
                rootRect: {
                    x: rect.x, y: rect.y,
                    width: rect.width, height: rect.height
                }
            } as TreemapRenderPayload);
        }
    }

    private _initEvents(containerGroup: graphic.Group) {
        containerGroup.on('click', (e) => {
            if (this._state !== 'ready') {
                return;
            }

            const nodeClick = this.seriesModel.get('nodeClick', true);

            if (!nodeClick) {
                return;
            }

            const targetInfo = this.findTarget(e.offsetX, e.offsetY);

            if (!targetInfo) {
                return;
            }

            const node = targetInfo.node;
            if (node.getLayout().isLeafRoot) {
                this._rootToNode(targetInfo);
            }
            else {
                if (nodeClick === 'zoomToNode') {
                    this._zoomToNode(targetInfo);
                }
                else if (nodeClick === 'link') {
                    const itemModel = node.hostTree.data.getItemModel<TreeSeriesNodeItemOption>(node.dataIndex);
                    const link = itemModel.get('link', true);
                    const linkTarget = itemModel.get('target', true) || 'blank';
                    link && windowOpen(link, linkTarget);
                }
            }

        }, this);
    }

    private _renderBreadcrumb(seriesModel: TreemapSeriesModel, api: ExtensionAPI, targetInfo: FoundTargetInfo) {
        if (!targetInfo) {
            targetInfo = seriesModel.get('leafDepth', true) != null
                ? {node: seriesModel.getViewRoot()}
                // FIXME
                // better way?
                // Find breadcrumb tail on center of containerGroup.
                : this.findTarget(api.getWidth() / 2, api.getHeight() / 2);

            if (!targetInfo) {
                targetInfo = {node: seriesModel.getData().tree.root};
            }
        }

        (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group)))
            .render(seriesModel, api, targetInfo.node, (node) => {
                if (this._state !== 'animating') {
                    helper.aboveViewRoot(seriesModel.getViewRoot(), node)
                        ? this._rootToNode({node: node})
                        : this._zoomToNode({node: node});
                }
            });
    }

    /**
     * @override
     */
    remove() {
        this._clearController();
        this._containerGroup && this._containerGroup.removeAll();
        this._storage = createStorage() as RenderElementStorage;
        this._state = 'ready';
        this._breadcrumb && this._breadcrumb.remove();
    }

    dispose() {
        this._clearController();
    }

    private _zoomToNode(targetInfo: FoundTargetInfo) {
        this.api.dispatchAction({
            type: 'treemapZoomToNode',
            from: this.uid,
            seriesId: this.seriesModel.id,
            targetNode: targetInfo.node
        });
    }

    private _rootToNode(targetInfo: FoundTargetInfo) {
        this.api.dispatchAction({
            type: 'treemapRootToNode',
            from: this.uid,
            seriesId: this.seriesModel.id,
            targetNode: targetInfo.node
        });
    }

    /**
     * @public
     * @param {number} x Global coord x.
     * @param {number} y Global coord y.
     * @return {Object} info If not found, return undefined;
     * @return {number} info.node Target node.
     * @return {number} info.offsetX x refer to target node.
     * @return {number} info.offsetY y refer to target node.
     */
    findTarget(x: number, y: number): FoundTargetInfo {
        let targetInfo;
        const viewRoot = this.seriesModel.getViewRoot();

        viewRoot.eachNode({attr: 'viewChildren', order: 'preorder'}, function (node) {
            const bgEl = this._storage.background[node.getRawIndex()];
            // If invisible, there might be no element.
            if (bgEl) {
                const point = bgEl.transformCoordToLocal(x, y);
                const shape = bgEl.shape;

                // For performance consideration, dont use 'getBoundingRect'.
                if (shape.x <= point[0]
                    && point[0] <= shape.x + shape.width
                    && shape.y <= point[1]
                    && point[1] <= shape.y + shape.height
                ) {
                    targetInfo = {
                        node: node,
                        offsetX: point[0],
                        offsetY: point[1]
                    };
                }
                else {
                    return false; // Suppress visit subtree.
                }
            }
        }, this);

        return targetInfo;
    }
}

/**
 * @inner
 */
function createStorage(): RenderElementStorage | LastCfgStorage {
    return {
        nodeGroup: [],
        background: [],
        content: []
    };
}

/**
 * @inner
 * @return Return undefined means do not travel further.
 */
function renderNode(
    seriesModel: TreemapSeriesModel,
    thisStorage: RenderElementStorage,
    oldStorage: RenderElementStorage,
    reRoot: ReRoot,
    lastsForAnimation: RenderResult['lastsForAnimation'],
    willInvisibleEls: RenderResult['willInvisibleEls'],
    thisNode: TreeNode,
    oldNode: TreeNode,
    parentGroup: graphic.Group,
    depth: number
) {
    // Whether under viewRoot.
    if (!thisNode) {
        // Deleting nodes will be performed finally. This method just find
        // element from old storage, or create new element, set them to new
        // storage, and set styles.
        return;
    }

    // -------------------------------------------------------------------
    // Start of closure variables available in "Procedures in renderNode".

    const thisLayout = thisNode.getLayout();
    const data = seriesModel.getData();
    const nodeModel = thisNode.getModel<TreemapSeriesNodeItemOption>();

    // Only for enabling highlight/downplay. Clear firstly.
    // Because some node will not be rendered.
    data.setItemGraphicEl(thisNode.dataIndex, null);

    if (!thisLayout || !thisLayout.isInView) {
        return;
    }

    const thisWidth = thisLayout.width;
    const thisHeight = thisLayout.height;
    const borderWidth = thisLayout.borderWidth;
    const thisInvisible = thisLayout.invisible;

    const thisRawIndex = thisNode.getRawIndex();
    const oldRawIndex = oldNode && oldNode.getRawIndex();

    const thisViewChildren = thisNode.viewChildren;
    const upperHeight = thisLayout.upperHeight;
    const isParent = thisViewChildren && thisViewChildren.length;
    const itemStyleNormalModel = nodeModel.getModel('itemStyle');
    const itemStyleEmphasisModel = nodeModel.getModel(['emphasis', 'itemStyle']);
    const itemStyleBlurModel = nodeModel.getModel(['blur', 'itemStyle']);
    const itemStyleSelectModel = nodeModel.getModel(['select', 'itemStyle']);
    const borderRadius = itemStyleNormalModel.get('borderRadius') || 0;

    // End of closure ariables available in "Procedures in renderNode".
    // -----------------------------------------------------------------

    // Node group
    const group = giveGraphic('nodeGroup', Group);

    if (!group) {
        return;
    }

    parentGroup.add(group);
    // x,y are not set when el is above view root.
    group.x = thisLayout.x || 0;
    group.y = thisLayout.y || 0;
    group.markRedraw();
    inner(group).nodeWidth = thisWidth;
    inner(group).nodeHeight = thisHeight;

    if (thisLayout.isAboveViewRoot) {
        return group;
    }

    // Background
    const bg = giveGraphic('background', Rect, depth, Z_BG);
    bg && renderBackground(group, bg, isParent && thisLayout.upperLabelHeight);

    const focus = nodeModel.get(['emphasis', 'focus']);
    const blurScope = nodeModel.get(['emphasis', 'blurScope']);

    const focusDataIndices: number[] = focus === 'ancestor'
        ? thisNode.getAncestorsIndices()
        : focus === 'descendant' ? thisNode.getDescendantIndices() : null;

    // No children, render content.
    if (isParent) {
        // Because of the implementation about "traverse" in graphic hover style, we
        // can not set hover listener on the "group" of non-leaf node. Otherwise the
        // hover event from the descendents will be listenered.
        if (isHighDownDispatcher(group)) {
            setAsHighDownDispatcher(group, false);
        }
        if (bg) {
            setAsHighDownDispatcher(bg, true);
            // Only for enabling highlight/downplay.
            data.setItemGraphicEl(thisNode.dataIndex, bg);

            enableHoverFocus(bg, focusDataIndices || focus, blurScope);
        }
    }
    else {
        const content = giveGraphic('content', Rect, depth, Z_CONTENT);
        content && renderContent(group, content);

        if (bg && isHighDownDispatcher(bg)) {
            setAsHighDownDispatcher(bg, false);
        }
        setAsHighDownDispatcher(group, true);
        // Only for enabling highlight/downplay.
        data.setItemGraphicEl(thisNode.dataIndex, group);

        enableHoverFocus(group, focusDataIndices || focus, blurScope);
    }

    return group;

    // ----------------------------
    // | Procedures in renderNode |
    // ----------------------------

    function renderBackground(group: graphic.Group, bg: graphic.Rect, useUpperLabel: boolean) {
        const ecData = getECData(bg);
        // For tooltip.
        ecData.dataIndex = thisNode.dataIndex;
        ecData.seriesIndex = seriesModel.seriesIndex;

        bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight, r: borderRadius});

        if (thisInvisible) {
            // If invisible, do not set visual, otherwise the element will
            // change immediately before animation. We think it is OK to
            // remain its origin color when moving out of the view window.
            processInvisible(bg);
        }
        else {
            bg.invisible = false;
            const style = thisNode.getVisual('style');
            const visualBorderColor = style.stroke;
            const normalStyle = getItemStyleNormal(itemStyleNormalModel);
            normalStyle.fill = visualBorderColor;
            const emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
            emphasisStyle.fill = itemStyleEmphasisModel.get('borderColor');
            const blurStyle = getStateItemStyle(itemStyleBlurModel);
            blurStyle.fill = itemStyleBlurModel.get('borderColor');
            const selectStyle = getStateItemStyle(itemStyleSelectModel);
            selectStyle.fill = itemStyleSelectModel.get('borderColor');

            if (useUpperLabel) {
                const upperLabelWidth = thisWidth - 2 * borderWidth;

                prepareText(
                    bg, visualBorderColor, upperLabelWidth, upperHeight, style.opacity,
                    {x: borderWidth, y: 0, width: upperLabelWidth, height: upperHeight}
                );
            }
            // For old bg.
            else {
                bg.removeTextContent();
            }

            bg.setStyle(normalStyle);

            bg.ensureState('emphasis').style = emphasisStyle;
            bg.ensureState('blur').style = blurStyle;
            bg.ensureState('select').style = selectStyle;
            setDefaultStateProxy(bg);
        }

        group.add(bg);
    }

    function renderContent(group: graphic.Group, content: graphic.Rect) {
        const ecData = getECData(content);
        // For tooltip.
        ecData.dataIndex = thisNode.dataIndex;
        ecData.seriesIndex = seriesModel.seriesIndex;

        const contentWidth = Math.max(thisWidth - 2 * borderWidth, 0);
        const contentHeight = Math.max(thisHeight - 2 * borderWidth, 0);

        content.culling = true;
        content.setShape({
            x: borderWidth,
            y: borderWidth,
            width: contentWidth,
            height: contentHeight,
            r: borderRadius
        });

        if (thisInvisible) {
            // If invisible, do not set visual, otherwise the element will
            // change immediately before animation. We think it is OK to
            // remain its origin color when moving out of the view window.
            processInvisible(content);
        }
        else {
            content.invisible = false;
            const nodeStyle = thisNode.getVisual('style');
            const visualColor = nodeStyle.fill;
            const normalStyle = getItemStyleNormal(itemStyleNormalModel);
            normalStyle.fill = visualColor;
            normalStyle.decal = nodeStyle.decal;
            const emphasisStyle = getStateItemStyle(itemStyleEmphasisModel);
            const blurStyle = getStateItemStyle(itemStyleBlurModel);
            const selectStyle = getStateItemStyle(itemStyleSelectModel);

            prepareText(content, visualColor, contentWidth, nodeStyle.opacity, contentHeight);

            content.setStyle(normalStyle);
            content.ensureState('emphasis').style = emphasisStyle;
            content.ensureState('blur').style = blurStyle;
            content.ensureState('select').style = selectStyle;
            setDefaultStateProxy(content);
        }

        group.add(content);
    }

    function processInvisible(element: graphic.Rect) {
        // Delay invisible setting utill animation finished,
        // avoid element vanish suddenly before animation.
        !element.invisible && willInvisibleEls.push(element);
    }

    function prepareText(
        rectEl: graphic.Rect,
        visualColor: ColorString,
        visualOpacity: number,
        width: number,
        height: number,
        upperLabelRect?: RectLike
    ) {
        const normalLabelModel = nodeModel.getModel(
            upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL
        );

        let text = retrieve(
            seriesModel.getFormattedLabel(
                thisNode.dataIndex, 'normal', null, null, normalLabelModel.get('formatter')
            ),
            convertOptionIdName(nodeModel.get('name'), null)
        );
        if (!upperLabelRect && thisLayout.isLeafRoot) {
            const iconChar = seriesModel.get('drillDownIcon', true);
            text = iconChar ? iconChar + ' ' + text : text;
        }

        const isShow = normalLabelModel.getShallow('show');

        setLabelStyle(
            rectEl,
            getLabelStatesModels(nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL),
            {
                defaultText: isShow ? text : null,
                inheritColor: visualColor,
                defaultOpacity: visualOpacity,
                labelFetcher: seriesModel,
                labelDataIndex: thisNode.dataIndex
            }
        );

        const textEl = rectEl.getTextContent();
        const textStyle = textEl.style;
        const textPadding = normalizeCssArray(textStyle.padding || 0);

        if (upperLabelRect) {
            rectEl.setTextConfig({
                layoutRect: upperLabelRect
            });
            (textEl as ECElement).disableLabelLayout = true;
        }
        textEl.beforeUpdate = function () {
            const width = Math.max(
                (upperLabelRect ? upperLabelRect.width : rectEl.shape.width) - textPadding[1] - textPadding[3], 0
            );
            const height = Math.max(
                (upperLabelRect ? upperLabelRect.height : rectEl.shape.height) - textPadding[0] - textPadding[2], 0
            );
            if (textStyle.width !== width || textStyle.height !== height) {
                textEl.setStyle({
                    width,
                    height
                });
            }
        };

        textStyle.truncateMinChar = 2;
        textStyle.lineOverflow = 'truncate';

        addDrillDownIcon(textStyle, upperLabelRect, thisLayout);
        const textEmphasisState = textEl.getState('emphasis');
        addDrillDownIcon(textEmphasisState ? textEmphasisState.style : null, upperLabelRect, thisLayout);
    }

    function addDrillDownIcon(style: TextStyleProps, upperLabelRect: RectLike, thisLayout: any) {
        const text = style ? style.text : null;
        if (!upperLabelRect && thisLayout.isLeafRoot && text != null) {
            const iconChar = seriesModel.get('drillDownIcon', true);
            style.text = iconChar ? iconChar + ' ' + text : text;
        }
    }

    function giveGraphic<T extends graphic.Group | graphic.Rect>(
        storageName: keyof RenderElementStorage,
        Ctor: {new(): T},
        depth?: number,
        z?: number
    ): T {
        let element = oldRawIndex != null && oldStorage[storageName][oldRawIndex];
        const lasts = lastsForAnimation[storageName];

        if (element) {
            // Remove from oldStorage
            oldStorage[storageName][oldRawIndex] = null;
            prepareAnimationWhenHasOld(lasts, element);
        }
        // If invisible and no old element, do not create new element (for optimizing).
        else if (!thisInvisible) {
            element = new Ctor();
            if (element instanceof Displayable) {
                element.z = calculateZ(depth, z);
            }
            prepareAnimationWhenNoOld(lasts, element);
        }

        // Set to thisStorage
        return (thisStorage[storageName][thisRawIndex] = element) as T;
    }

    function prepareAnimationWhenHasOld(lasts: LastCfg[], element: graphic.Group | graphic.Rect) {
        const lastCfg = lasts[thisRawIndex] = {} as LastCfg;
        if (element instanceof Group) {
            lastCfg.oldX = element.x;
            lastCfg.oldY = element.y;
        }
        else {
            lastCfg.oldShape = extend({}, element.shape);
        }
    }

    // If a element is new, we need to find the animation start point carefully,
    // otherwise it will looks strange when 'zoomToNode'.
    function prepareAnimationWhenNoOld(lasts: LastCfg[], element: graphic.Group | graphic.Rect) {
        const lastCfg = lasts[thisRawIndex] = {} as LastCfg;
        const parentNode = thisNode.parentNode;
        const isGroup = element instanceof graphic.Group;

        if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) {
            let parentOldX = 0;
            let parentOldY = 0;

            // New nodes appear from right-bottom corner in 'zoomToNode' animation.
            // For convenience, get old bounding rect from background.
            const parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()];
            if (!reRoot && parentOldBg && parentOldBg.oldShape) {
                parentOldX = parentOldBg.oldShape.width;
                parentOldY = parentOldBg.oldShape.height;
            }

            // When no parent old shape found, its parent is new too,
            // so we can just use {x:0, y:0}.
            if (isGroup) {
                lastCfg.oldX = 0;
                lastCfg.oldY = parentOldY;
            }
            else {
                lastCfg.oldShape = {x: parentOldX, y: parentOldY, width: 0, height: 0};
            }
        }

        // Fade in, user can be aware that these nodes are new.
        lastCfg.fadein = !isGroup;
    }

}

// We can not set all backgroud with the same z, Because the behaviour of
// drill down and roll up differ background creation sequence from tree
// hierarchy sequence, which cause that lowser background element overlap
// upper ones. So we calculate z based on depth.
// Moreover, we try to shrink down z interval to [0, 1] to avoid that
// treemap with large z overlaps other components.
function calculateZ(depth: number, zInLevel: number) {
    const zb = depth * Z_BASE + zInLevel;
    return (zb - 1) / zb;
}

export default TreemapView;