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

import * as zrUtil from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import {
    enableHoverEmphasis
} from '../../util/states';
import {createSymbol, normalizeSymbolOffset} from '../../util/symbol';
import {parsePercent, isNumeric} from '../../util/number';
import ChartView from '../../view/Chart';
import PictorialBarSeriesModel, {PictorialBarDataItemOption} from './PictorialBarSeries';
import ExtensionAPI from '../../core/ExtensionAPI';
import List from '../../data/List';
import GlobalModel from '../../model/Global';
import Model from '../../model/Model';
import { ColorString, AnimationOptionMixin, ECElement } from '../../util/types';
import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
import type Displayable from 'zrender/src/graphic/Displayable';
import type Axis2D from '../../coord/cartesian/Axis2D';
import type Element from 'zrender/src/Element';
import { getDefaultLabel } from '../helper/labelHelper';
import { PathProps, PathStyleProps } from 'zrender/src/graphic/Path';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
import ZRImage from 'zrender/src/graphic/Image';
import { getECData } from '../../util/innerStore';

const BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth'] as const;

// index: +isHorizontal
const LAYOUT_ATTRS = [
    {xy: 'x', wh: 'width', index: 0, posDesc: ['left', 'right']},
    {xy: 'y', wh: 'height', index: 1, posDesc: ['top', 'bottom']}
] as const;

const pathForLineWidth = new graphic.Circle();

type ItemModel = Model<PictorialBarDataItemOption> & {
    getAnimationDelayParams(path: any): {index: number, count: number}
    isAnimationEnabled(): boolean
};
type RectShape = graphic.Rect['shape'];
type RectLayout = RectShape;

type PictorialSymbol = ReturnType<typeof createSymbol> & {
    __pictorialAnimationIndex: number
    __pictorialRepeatTimes: number
};

interface SymbolMeta {
    dataIndex: number

    symbolPatternSize: number
    symbolType: string
    symbolMargin: number
    symbolSize: number[]
    symbolScale: number[]
    symbolRepeat: PictorialBarDataItemOption['symbolRepeat']
    symbolClip: PictorialBarDataItemOption['symbolClip']
    symbolRepeatDirection: PictorialBarDataItemOption['symbolRepeatDirection']

    layout: RectLayout

    repeatTimes: number

    rotation: number

    pathPosition: number[]
    bundlePosition: number[]

    pxSign: number

    barRectShape: RectShape
    clipShape: RectShape

    boundingLength: number
    repeatCutLength: number

    valueLineWidth: number

    opacity: number
    style: PathStyleProps
    z2: number

    itemModel: ItemModel

    animationModel?: ItemModel

    hoverScale: boolean
}

interface CreateOpts {
    ecSize: { width: number, height: number }
    seriesModel: PictorialBarSeriesModel
    coordSys: Cartesian2D
    coordSysExtent: number[][]
    isHorizontal: boolean
    valueDim: typeof LAYOUT_ATTRS[number]
    categoryDim: typeof LAYOUT_ATTRS[number]
}

interface PictorialBarElement extends graphic.Group {
    __pictorialBundle: graphic.Group
    __pictorialShapeStr: string
    __pictorialSymbolMeta: SymbolMeta

    __pictorialMainPath: PictorialSymbol

    __pictorialBarRect: graphic.Rect

    __pictorialClipPath: graphic.Rect
}

class PictorialBarView extends ChartView {
    static type = 'pictorialBar';
    readonly type = PictorialBarView.type;

    private _data: List;

    render(
        seriesModel: PictorialBarSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI
    ) {
        const group = this.group;
        const data = seriesModel.getData();
        const oldData = this._data;

        const cartesian = seriesModel.coordinateSystem;
        const baseAxis = cartesian.getBaseAxis();
        const isHorizontal = baseAxis.isHorizontal();
        const coordSysRect = cartesian.master.getRect();

        const opt: CreateOpts = {
            ecSize: {width: api.getWidth(), height: api.getHeight()},
            seriesModel: seriesModel,
            coordSys: cartesian,
            coordSysExtent: [
                [coordSysRect.x, coordSysRect.x + coordSysRect.width],
                [coordSysRect.y, coordSysRect.y + coordSysRect.height]
            ],
            isHorizontal: isHorizontal,
            valueDim: LAYOUT_ATTRS[+isHorizontal],
            categoryDim: LAYOUT_ATTRS[1 - (+isHorizontal)]
        };

        data.diff(oldData)
            .add(function (dataIndex) {
                if (!data.hasValue(dataIndex)) {
                    return;
                }

                const itemModel = getItemModel(data, dataIndex);
                const symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt);

                const bar = createBar(data, opt, symbolMeta);

                data.setItemGraphicEl(dataIndex, bar);
                group.add(bar);

                updateCommon(bar, opt, symbolMeta);
            })
            .update(function (newIndex, oldIndex) {
                let bar = oldData.getItemGraphicEl(oldIndex) as PictorialBarElement;

                if (!data.hasValue(newIndex)) {
                    group.remove(bar);
                    return;
                }

                const itemModel = getItemModel(data, newIndex);
                const symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt);

                const pictorialShapeStr = getShapeStr(data, symbolMeta);
                if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) {
                    group.remove(bar);
                    data.setItemGraphicEl(newIndex, null);
                    bar = null;
                }

                if (bar) {
                    updateBar(bar, opt, symbolMeta);
                }
                else {
                    bar = createBar(data, opt, symbolMeta, true);
                }

                data.setItemGraphicEl(newIndex, bar);
                bar.__pictorialSymbolMeta = symbolMeta;
                // Add back
                group.add(bar);

                updateCommon(bar, opt, symbolMeta);
            })
            .remove(function (dataIndex) {
                const bar = oldData.getItemGraphicEl(dataIndex) as PictorialBarElement;
                bar && removeBar(
                    oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar
                );
            })
            .execute();

        this._data = data;

        return this.group;
    }

    remove(ecModel: GlobalModel, api: ExtensionAPI) {
        const group = this.group;
        const data = this._data;
        if (ecModel.get('animation')) {
            if (data) {
                data.eachItemGraphicEl(function (bar: PictorialBarElement) {
                    removeBar(data, getECData(bar).dataIndex, ecModel as Model<AnimationOptionMixin>, bar);
                });
            }
        }
        else {
            group.removeAll();
        }
    }
}

// Set or calculate default value about symbol, and calculate layout info.
function getSymbolMeta(
    data: List,
    dataIndex: number,
    itemModel: ItemModel,
    opt: CreateOpts
): SymbolMeta {
    const layout = data.getItemLayout(dataIndex) as RectLayout;
    const symbolRepeat = itemModel.get('symbolRepeat');
    const symbolClip = itemModel.get('symbolClip');
    const symbolPosition = itemModel.get('symbolPosition') || 'start';
    const symbolRotate = itemModel.get('symbolRotate');
    const rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
    const symbolPatternSize = itemModel.get('symbolPatternSize') || 2;
    const isAnimationEnabled = itemModel.isAnimationEnabled();

    const symbolMeta: SymbolMeta = {
        dataIndex: dataIndex,
        layout: layout,
        itemModel: itemModel,
        symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle',
        style: data.getItemVisual(dataIndex, 'style'),
        symbolClip: symbolClip,
        symbolRepeat: symbolRepeat,
        symbolRepeatDirection: itemModel.get('symbolRepeatDirection'),
        symbolPatternSize: symbolPatternSize,
        rotation: rotation,
        animationModel: isAnimationEnabled ? itemModel : null,
        hoverScale: isAnimationEnabled && itemModel.get(['emphasis', 'scale']),
        z2: itemModel.getShallow('z', true) || 0
    } as SymbolMeta;

    prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta);

    prepareSymbolSize(
        data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength,
        symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta
    );

    prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta);

    const symbolSize = symbolMeta.symbolSize;
    const symbolOffset = normalizeSymbolOffset(itemModel.get('symbolOffset'), symbolSize);

    prepareLayoutInfo(
        itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset as number[],
        symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength,
        opt, symbolMeta
    );

    return symbolMeta;
}

// bar length can be negative.
function prepareBarLength(
    itemModel: ItemModel,
    symbolRepeat: PictorialBarDataItemOption['symbolRepeat'],
    layout: RectLayout,
    opt: CreateOpts,
    outputSymbolMeta: SymbolMeta
) {
    const valueDim = opt.valueDim;
    const symbolBoundingData = itemModel.get('symbolBoundingData');
    const valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis());
    const zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0));
    const pxSignIdx = 1 - +(layout[valueDim.wh] <= 0);
    let boundingLength;

    if (zrUtil.isArray(symbolBoundingData)) {
        const symbolBoundingExtent = [
            convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx,
            convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx
        ];
        symbolBoundingExtent[1] < symbolBoundingExtent[0] && (symbolBoundingExtent.reverse());
        boundingLength = symbolBoundingExtent[pxSignIdx];
    }
    else if (symbolBoundingData != null) {
        boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx;
    }
    else if (symbolRepeat) {
        boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx;
    }
    else {
        boundingLength = layout[valueDim.wh];
    }

    outputSymbolMeta.boundingLength = boundingLength;

    if (symbolRepeat) {
        outputSymbolMeta.repeatCutLength = layout[valueDim.wh];
    }

    outputSymbolMeta.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0;
}

function convertToCoordOnAxis(axis: Axis2D, value: number) {
    return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value)));
}

// Support ['100%', '100%']
function prepareSymbolSize(
    data: List,
    dataIndex: number,
    layout: RectLayout,
    symbolRepeat: PictorialBarDataItemOption['symbolRepeat'],
    symbolClip: unknown,
    boundingLength: number,
    pxSign: number,
    symbolPatternSize: number,
    opt: CreateOpts,
    outputSymbolMeta: SymbolMeta
) {
    const valueDim = opt.valueDim;
    const categoryDim = opt.categoryDim;
    const categorySize = Math.abs(layout[categoryDim.wh]);

    const symbolSize = data.getItemVisual(dataIndex, 'symbolSize');
    let parsedSymbolSize: number[];
    if (zrUtil.isArray(symbolSize)) {
        parsedSymbolSize = symbolSize.slice();
    }
    else {
        if (symbolSize == null) {
            // will parse to number below
            parsedSymbolSize = ['100%', '100%'] as unknown as number[];
        }
        else {
            parsedSymbolSize = [symbolSize, symbolSize];
        }
    }

    // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is
    // to complicated to calculate real percent value if considering scaled lineWidth.
    // So the actual size will bigger than layout size if lineWidth is bigger than zero,
    // which can be tolerated in pictorial chart.

    parsedSymbolSize[categoryDim.index] = parsePercent(
        parsedSymbolSize[categoryDim.index],
        categorySize
    );
    parsedSymbolSize[valueDim.index] = parsePercent(
        parsedSymbolSize[valueDim.index],
        symbolRepeat ? categorySize : Math.abs(boundingLength)
    );

    outputSymbolMeta.symbolSize = parsedSymbolSize;

    // If x or y is less than zero, show reversed shape.
    const symbolScale = outputSymbolMeta.symbolScale = [
        parsedSymbolSize[0] / symbolPatternSize,
        parsedSymbolSize[1] / symbolPatternSize
    ];
    // Follow convention, 'right' and 'top' is the normal scale.
    symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign;
}

function prepareLineWidth(
    itemModel: ItemModel,
    symbolScale: number[],
    rotation: number,
    opt: CreateOpts,
    outputSymbolMeta: SymbolMeta
) {
    // In symbols are drawn with scale, so do not need to care about the case that width
    // or height are too small. But symbol use strokeNoScale, where acture lineWidth should
    // be calculated.
    let valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;

    if (valueLineWidth) {
        pathForLineWidth.attr({
            scaleX: symbolScale[0],
            scaleY: symbolScale[1],
            rotation: rotation
        });
        pathForLineWidth.updateTransform();
        valueLineWidth /= pathForLineWidth.getLineScale();
        valueLineWidth *= symbolScale[opt.valueDim.index];
    }

    outputSymbolMeta.valueLineWidth = valueLineWidth;
}

function prepareLayoutInfo(
    itemModel: ItemModel,
    symbolSize: number[],
    layout: RectLayout,
    symbolRepeat: PictorialBarDataItemOption['symbolRepeat'],
    symbolClip: PictorialBarDataItemOption['symbolClip'],
    symbolOffset: number[],
    symbolPosition: PictorialBarDataItemOption['symbolPosition'],
    valueLineWidth: number,
    boundingLength: number,
    repeatCutLength: number,
    opt: CreateOpts,
    outputSymbolMeta: SymbolMeta
) {
    const categoryDim = opt.categoryDim;
    const valueDim = opt.valueDim;
    const pxSign = outputSymbolMeta.pxSign;

    const unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0);
    let pathLen = unitLength;

    // Note: rotation will not effect the layout of symbols, because user may
    // want symbols to rotate on its center, which should not be translated
    // when rotating.

    if (symbolRepeat) {
        const absBoundingLength = Math.abs(boundingLength);

        let symbolMargin = zrUtil.retrieve(itemModel.get('symbolMargin'), '15%') + '';
        let hasEndGap = false;
        if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) {
            hasEndGap = true;
            symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1);
        }
        let symbolMarginNumeric = parsePercent(symbolMargin, symbolSize[valueDim.index]);

        let uLenWithMargin = Math.max(unitLength + symbolMarginNumeric * 2, 0);

        // When symbol margin is less than 0, margin at both ends will be subtracted
        // to ensure that all of the symbols will not be overflow the given area.
        let endFix = hasEndGap ? 0 : symbolMarginNumeric * 2;

        // Both final repeatTimes and final symbolMarginNumeric area calculated based on
        // boundingLength.
        const repeatSpecified = isNumeric(symbolRepeat);
        let repeatTimes = repeatSpecified
            ? symbolRepeat as number
            : toIntTimes((absBoundingLength + endFix) / uLenWithMargin);

        // Adjust calculate margin, to ensure each symbol is displayed
        // entirely in the given layout area.
        const mDiff = absBoundingLength - repeatTimes * unitLength;
        symbolMarginNumeric = mDiff / 2 / (hasEndGap ? repeatTimes : Math.max(repeatTimes - 1, 1));
        uLenWithMargin = unitLength + symbolMarginNumeric * 2;
        endFix = hasEndGap ? 0 : symbolMarginNumeric * 2;

        // Update repeatTimes when not all symbol will be shown.
        if (!repeatSpecified && symbolRepeat !== 'fixed') {
            repeatTimes = repeatCutLength
                ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin)
                : 0;
        }

        pathLen = repeatTimes * uLenWithMargin - endFix;
        outputSymbolMeta.repeatTimes = repeatTimes;
        outputSymbolMeta.symbolMargin = symbolMarginNumeric;
    }

    const sizeFix = pxSign * (pathLen / 2);
    const pathPosition = outputSymbolMeta.pathPosition = [] as number[];
    pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2;
    pathPosition[valueDim.index] = symbolPosition === 'start'
        ? sizeFix
        : symbolPosition === 'end'
        ? boundingLength - sizeFix
        : boundingLength / 2; // 'center'
    if (symbolOffset) {
        pathPosition[0] += symbolOffset[0];
        pathPosition[1] += symbolOffset[1];
    }

    const bundlePosition = outputSymbolMeta.bundlePosition = [] as number[];
    bundlePosition[categoryDim.index] = layout[categoryDim.xy];
    bundlePosition[valueDim.index] = layout[valueDim.xy];

    const barRectShape = outputSymbolMeta.barRectShape = zrUtil.extend({}, layout);
    barRectShape[valueDim.wh] = pxSign * Math.max(
        Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)
    );
    barRectShape[categoryDim.wh] = layout[categoryDim.wh];

    const clipShape = outputSymbolMeta.clipShape = {} as RectShape;
    // Consider that symbol may be overflow layout rect.
    clipShape[categoryDim.xy] = -layout[categoryDim.xy];
    clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh];
    clipShape[valueDim.xy] = 0;
    clipShape[valueDim.wh] = layout[valueDim.wh];
}

function createPath(symbolMeta: SymbolMeta) {
    const symbolPatternSize = symbolMeta.symbolPatternSize;
    const path = createSymbol(
        // Consider texture img, make a big size.
        symbolMeta.symbolType,
        -symbolPatternSize / 2,
        -symbolPatternSize / 2,
        symbolPatternSize,
        symbolPatternSize
    );
    (path as Displayable).attr({
        culling: true
    });
    path.type !== 'image' && path.setStyle({
        strokeNoScale: true
    });

    return path as PictorialSymbol;
}

function createOrUpdateRepeatSymbols(
    bar: PictorialBarElement, opt: CreateOpts, symbolMeta: SymbolMeta, isUpdate?: boolean
) {
    const bundle = bar.__pictorialBundle;
    const symbolSize = symbolMeta.symbolSize;
    const valueLineWidth = symbolMeta.valueLineWidth;
    const pathPosition = symbolMeta.pathPosition;
    const valueDim = opt.valueDim;
    const repeatTimes = symbolMeta.repeatTimes || 0;

    let index = 0;
    const unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2;

    eachPath(bar, function (path) {
        path.__pictorialAnimationIndex = index;
        path.__pictorialRepeatTimes = repeatTimes;
        if (index < repeatTimes) {
            updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate);
        }
        else {
            updateAttr(path, null, { scaleX: 0, scaleY: 0 }, symbolMeta, isUpdate, function () {
                bundle.remove(path);
            });
        }

        // updateHoverAnimation(path, symbolMeta);

        index++;
    });

    for (; index < repeatTimes; index++) {
        const path = createPath(symbolMeta);
        path.__pictorialAnimationIndex = index;
        path.__pictorialRepeatTimes = repeatTimes;
        bundle.add(path);

        const target = makeTarget(index);

        updateAttr(
            path,
            {
                x: target.x,
                y: target.y,
                scaleX: 0,
                scaleY: 0
            },
            {
                scaleX: target.scaleX,
                scaleY: target.scaleY,
                rotation: target.rotation
            },
            symbolMeta,
            isUpdate
        );
    }

    function makeTarget(index: number) {
        const position = pathPosition.slice();
        // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index
        // Otherwise: i = index;
        const pxSign = symbolMeta.pxSign;
        let i = index;
        if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) {
            i = repeatTimes - 1 - index;
        }
        position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index];

        return {
            x: position[0],
            y: position[1],
            scaleX: symbolMeta.symbolScale[0],
            scaleY: symbolMeta.symbolScale[1],
            rotation: symbolMeta.rotation
        };
    }
}

function createOrUpdateSingleSymbol(
    bar: PictorialBarElement,
    opt: CreateOpts,
    symbolMeta: SymbolMeta,
    isUpdate?: boolean
) {
    const bundle = bar.__pictorialBundle;
    let mainPath = bar.__pictorialMainPath;

    if (!mainPath) {
        mainPath = bar.__pictorialMainPath = createPath(symbolMeta);
        bundle.add(mainPath);

        updateAttr(
            mainPath,
            {
                x: symbolMeta.pathPosition[0],
                y: symbolMeta.pathPosition[1],
                scaleX: 0,
                scaleY: 0,
                rotation: symbolMeta.rotation
            },
            {
                scaleX: symbolMeta.symbolScale[0],
                scaleY: symbolMeta.symbolScale[1]
            },
            symbolMeta,
            isUpdate
        );
    }
    else {
        updateAttr(
            mainPath,
            null,
            {
                x: symbolMeta.pathPosition[0],
                y: symbolMeta.pathPosition[1],
                scaleX: symbolMeta.symbolScale[0],
                scaleY: symbolMeta.symbolScale[1],
                rotation: symbolMeta.rotation
            },
            symbolMeta,
            isUpdate
        );
    }
}

// bar rect is used for label.
function createOrUpdateBarRect(
    bar: PictorialBarElement,
    symbolMeta: SymbolMeta,
    isUpdate?: boolean
) {
    const rectShape = zrUtil.extend({}, symbolMeta.barRectShape);

    let barRect = bar.__pictorialBarRect;
    if (!barRect) {
        barRect = bar.__pictorialBarRect = new graphic.Rect({
            z2: 2,
            shape: rectShape,
            silent: true,
            style: {
                stroke: 'transparent',
                fill: 'transparent',
                lineWidth: 0
            }
        });
        (barRect as ECElement).disableMorphing = true;

        bar.add(barRect);
    }
    else {
        updateAttr(barRect, null, {shape: rectShape}, symbolMeta, isUpdate);
    }
}

function createOrUpdateClip(
    bar: PictorialBarElement,
    opt: CreateOpts,
    symbolMeta: SymbolMeta,
    isUpdate?: boolean
) {
    // If not clip, symbol will be remove and rebuilt.
    if (symbolMeta.symbolClip) {
        let clipPath = bar.__pictorialClipPath;
        const clipShape = zrUtil.extend({}, symbolMeta.clipShape);
        const valueDim = opt.valueDim;
        const animationModel = symbolMeta.animationModel;
        const dataIndex = symbolMeta.dataIndex;

        if (clipPath) {
            graphic.updateProps(
                clipPath, {shape: clipShape}, animationModel, dataIndex
            );
        }
        else {
            clipShape[valueDim.wh] = 0;
            clipPath = new graphic.Rect({shape: clipShape});
            bar.__pictorialBundle.setClipPath(clipPath);
            bar.__pictorialClipPath = clipPath;

            const target = {} as RectShape;
            target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh];

            graphic[isUpdate ? 'updateProps' : 'initProps'](
                clipPath, {shape: target}, animationModel, dataIndex
            );
        }
    }
}

function getItemModel(data: List, dataIndex: number) {
    const itemModel = data.getItemModel(dataIndex) as ItemModel;
    itemModel.getAnimationDelayParams = getAnimationDelayParams;
    itemModel.isAnimationEnabled = isAnimationEnabled;
    return itemModel;
}

function getAnimationDelayParams(this: ItemModel, path: PictorialSymbol) {
    // The order is the same as the z-order, see `symbolRepeatDiretion`.
    return {
        index: path.__pictorialAnimationIndex,
        count: path.__pictorialRepeatTimes
    };
}

function isAnimationEnabled(this: ItemModel) {
    // `animation` prop can be set on itemModel in pictorial bar chart.
    return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation');
}

function createBar(data: List, opt: CreateOpts, symbolMeta: SymbolMeta, isUpdate?: boolean) {
    // bar is the main element for each data.
    const bar = new graphic.Group() as PictorialBarElement;
    // bundle is used for location and clip.
    const bundle = new graphic.Group();
    bar.add(bundle);
    bar.__pictorialBundle = bundle;

    bundle.x = symbolMeta.bundlePosition[0];
    bundle.y = symbolMeta.bundlePosition[1];

    if (symbolMeta.symbolRepeat) {
        createOrUpdateRepeatSymbols(bar, opt, symbolMeta);
    }
    else {
        createOrUpdateSingleSymbol(bar, opt, symbolMeta);
    }

    createOrUpdateBarRect(bar, symbolMeta, isUpdate);

    createOrUpdateClip(bar, opt, symbolMeta, isUpdate);

    bar.__pictorialShapeStr = getShapeStr(data, symbolMeta);
    bar.__pictorialSymbolMeta = symbolMeta;
    return bar;
}

function updateBar(bar: PictorialBarElement, opt: CreateOpts, symbolMeta: SymbolMeta) {
    const animationModel = symbolMeta.animationModel;
    const dataIndex = symbolMeta.dataIndex;
    const bundle = bar.__pictorialBundle;

    graphic.updateProps(
        bundle, {
            x: symbolMeta.bundlePosition[0],
            y: symbolMeta.bundlePosition[1]
        }, animationModel, dataIndex
    );

    if (symbolMeta.symbolRepeat) {
        createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true);
    }
    else {
        createOrUpdateSingleSymbol(bar, opt, symbolMeta, true);
    }

    createOrUpdateBarRect(bar, symbolMeta, true);

    createOrUpdateClip(bar, opt, symbolMeta, true);
}

function removeBar(
    data: List, dataIndex: number, animationModel: Model<AnimationOptionMixin>, bar: PictorialBarElement
) {
    // Not show text when animating
    const labelRect = bar.__pictorialBarRect;
    labelRect && (labelRect.removeTextContent());

    const pathes = [];
    eachPath(bar, function (path) {
        pathes.push(path);
    });
    bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath);

    // I do not find proper remove animation for clip yet.
    bar.__pictorialClipPath && (animationModel = null);

    zrUtil.each(pathes, function (path) {
        graphic.removeElement(
            path, { scaleX: 0, scaleY: 0 }, animationModel, dataIndex,
            function () {
                bar.parent && bar.parent.remove(bar);
            }
        );
    });

    data.setItemGraphicEl(dataIndex, null);
}

function getShapeStr(data: List, symbolMeta: SymbolMeta) {
    return [
        data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none',
        !!symbolMeta.symbolRepeat,
        !!symbolMeta.symbolClip
    ].join(':');
}

function eachPath<Ctx>(
    bar: PictorialBarElement,
    cb: (this: Ctx, el: PictorialSymbol) => void,
    context?: Ctx
) {
    // Do not use Group#eachChild, because it do not support remove.
    zrUtil.each(bar.__pictorialBundle.children(), function (el) {
        el !== bar.__pictorialBarRect && cb.call(context, el);
    });
}

function updateAttr<T extends Element>(
    el: T,
    immediateAttrs: PathProps,
    animationAttrs: PathProps,
    symbolMeta: SymbolMeta,
    isUpdate?: boolean,
    cb?: () => void
) {
    immediateAttrs && el.attr(immediateAttrs);
    // when symbolCip used, only clip path has init animation, otherwise it would be weird effect.
    if (symbolMeta.symbolClip && !isUpdate) {
        animationAttrs && el.attr(animationAttrs);
    }
    else {
        animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](
            el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb
        );
    }
}

function updateCommon(
    bar: PictorialBarElement,
    opt: CreateOpts,
    symbolMeta: SymbolMeta
) {
    const dataIndex = symbolMeta.dataIndex;
    const itemModel = symbolMeta.itemModel;
    // Color must be excluded.
    // Because symbol provide setColor individually to set fill and stroke
    const emphasisModel = itemModel.getModel('emphasis');
    const emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle();
    const blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle();
    const selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle();
    const cursorStyle = itemModel.getShallow('cursor');

    const focus = emphasisModel.get('focus');
    const blurScope = emphasisModel.get('blurScope');
    const hoverScale = emphasisModel.get('scale');

    eachPath(bar, function (path) {
        if (path instanceof ZRImage) {
            const pathStyle = path.style;
            path.useStyle(zrUtil.extend({
                // TODO other properties like dx, dy ?
                image: pathStyle.image,
                x: pathStyle.x, y: pathStyle.y,
                width: pathStyle.width, height: pathStyle.height
            }, symbolMeta.style));
        }
        else {
            path.useStyle(symbolMeta.style);
        }

        const emphasisState = path.ensureState('emphasis');
        emphasisState.style = emphasisStyle;

        if (hoverScale) {
            // NOTE: Must after scale is set after updateAttr
            emphasisState.scaleX = path.scaleX * 1.1;
            emphasisState.scaleY = path.scaleY * 1.1;
        }

        path.ensureState('blur').style = blurStyle;
        path.ensureState('select').style = selectStyle;

        cursorStyle && (path.cursor = cursorStyle);
        path.z2 = symbolMeta.z2;
    });

    const barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)];
    const barRect = bar.__pictorialBarRect;

    setLabelStyle(
        barRect, getLabelStatesModels(itemModel),
        {
            labelFetcher: opt.seriesModel,
            labelDataIndex: dataIndex,
            defaultText: getDefaultLabel(opt.seriesModel.getData(), dataIndex),
            inheritColor: symbolMeta.style.fill as ColorString,
            defaultOpacity: symbolMeta.style.opacity,
            defaultOutsidePosition: barPositionOutside
        }
    );

    enableHoverEmphasis(bar, focus, blurScope);
}

function toIntTimes(times: number) {
    const roundedTimes = Math.round(times);
    // Escapse accurate error
    return Math.abs(times - roundedTimes) < 1e-4
        ? roundedTimes
        : Math.ceil(times);
}

export default PictorialBarView;
