/*
* 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 Path, {PathProps} from 'zrender/src/graphic/Path';
import Group from 'zrender/src/graphic/Group';
import {extend, each, map} from 'zrender/src/core/util';
import {BuiltinTextPosition} from 'zrender/src/core/types';
import {
    Rect,
    Sector,
    updateProps,
    initProps,
    removeElementWithFadeOut,
    traverseElements
} from '../../util/graphic';
import { getECData } from '../../util/innerStore';
import { setStatesStylesFromModel, toggleHoverEmphasis } from '../../util/states';
import { setLabelStyle, getLabelStatesModels, setLabelValueAnimation, labelInner } from '../../label/labelStyle';
import {throttle} from '../../util/throttle';
import {createClipPath} from '../helper/createClipPathFromCoordSys';
import Sausage from '../../util/shape/sausage';
import ChartView from '../../view/Chart';
import SeriesData, {DefaultDataVisual} from '../../data/SeriesData';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import {
    StageHandlerProgressParams,
    ZRElementEvent,
    ColorString,
    OrdinalSortInfo,
    Payload,
    OrdinalNumber,
    ParsedValue,
    ECElement
} from '../../util/types';
import BarSeriesModel, {BarDataItemOption, PolarBarLabelPosition} from './BarSeries';
import type Axis2D from '../../coord/cartesian/Axis2D';
import type Cartesian2D from '../../coord/cartesian/Cartesian2D';
import type Polar from '../../coord/polar/Polar';
import type Model from '../../model/Model';
import { isCoordinateSystemType } from '../../coord/CoordinateSystem';
import { getDefaultLabel, getDefaultInterpolatedLabel } from '../helper/labelHelper';
import OrdinalScale from '../../scale/Ordinal';
import SeriesModel from '../../model/Series';
import {AngleAxisModel, RadiusAxisModel} from '../../coord/polar/AxisModel';
import CartesianAxisModel from '../../coord/cartesian/AxisModel';
import {LayoutRect} from '../../util/layout';
import {EventCallback} from 'zrender/src/core/Eventful';
import { warn } from '../../util/log';
import {createSectorCalculateTextPosition, SectorTextPosition, setSectorTextRotation} from '../../label/sectorLabel';
import { saveOldStyle } from '../../animation/basicTransition';
import Element from 'zrender/src/Element';

const mathMax = Math.max;
const mathMin = Math.min;

type CoordSysOfBar = BarSeriesModel['coordinateSystem'];
type RectShape = Rect['shape'];
type SectorShape = Sector['shape'];

type SectorLayout = SectorShape;
type RectLayout = RectShape;

type BarPossiblePath = Sector | Rect | Sausage;

type CartesianCoordArea = ReturnType<Cartesian2D['getArea']>;
type PolarCoordArea = ReturnType<Polar['getArea']>;

type RealtimeSortConfig = {
    baseAxis: Axis2D;
    otherAxis: Axis2D;
};
// Return a number, based on which the ordinal sorted.
type OrderMapping = (dataIndex: number) => number;

function getClipArea(coord: CoordSysOfBar, data: SeriesData) {
    const coordSysClipArea = coord.getArea && coord.getArea();
    if (isCoordinateSystemType<Cartesian2D>(coord, 'cartesian2d')) {
        const baseAxis = coord.getBaseAxis();
        // When boundaryGap is false or using time axis. bar may exceed the grid.
        // We should not clip this part.
        // See test/bar2.html
        if (baseAxis.type !== 'category' || !baseAxis.onBand) {
            const expandWidth = data.getLayout('bandWidth');
            if (baseAxis.isHorizontal()) {
                (coordSysClipArea as CartesianCoordArea).x -= expandWidth;
                (coordSysClipArea as CartesianCoordArea).width += expandWidth * 2;
            }
            else {
                (coordSysClipArea as CartesianCoordArea).y -= expandWidth;
                (coordSysClipArea as CartesianCoordArea).height += expandWidth * 2;
            }
        }
    }

    return coordSysClipArea as PolarCoordArea | CartesianCoordArea;
}

class BarView extends ChartView {
    static type = 'bar' as const;
    type = BarView.type;

    private _data: SeriesData;

    private _isLargeDraw: boolean;

    private _isFirstFrame: boolean; // First frame after series added
    private _onRendered: EventCallback;

    private _backgroundGroup: Group;

    private _backgroundEls: (Rect | Sector)[];

    private _model: BarSeriesModel;

    private _progressiveEls: Element[];

    constructor() {
        super();
        this._isFirstFrame = true;
    }

    render(seriesModel: BarSeriesModel, ecModel: GlobalModel, api: ExtensionAPI, payload: Payload) {
        this._model = seriesModel;

        this._removeOnRenderedListener(api);

        this._updateDrawMode(seriesModel);

        const coordinateSystemType = seriesModel.get('coordinateSystem');

        if (coordinateSystemType === 'cartesian2d'
            || coordinateSystemType === 'polar'
        ) {
            // Clear previously rendered progressive elements.
            this._progressiveEls = null;

            this._isLargeDraw
                ? this._renderLarge(seriesModel, ecModel, api)
                : this._renderNormal(seriesModel, ecModel, api, payload);
        }
        else if (__DEV__) {
            warn('Only cartesian2d and polar supported for bar.');
        }
    }

    incrementalPrepareRender(seriesModel: BarSeriesModel): void {
        this._clear();
        this._updateDrawMode(seriesModel);
        // incremental also need to clip, otherwise might be overlow.
        // But must not set clip in each frame, otherwise all of the children will be marked redraw.
        this._updateLargeClip(seriesModel);
    }

    incrementalRender(params: StageHandlerProgressParams, seriesModel: BarSeriesModel): void {
        // Reset
        this._progressiveEls = [];
        // Do not support progressive in normal mode.
        this._incrementalRenderLarge(params, seriesModel);
    }

    eachRendered(cb: (el: Element) => boolean | void) {
        traverseElements(this._progressiveEls || this.group, cb);
    }

    private _updateDrawMode(seriesModel: BarSeriesModel): void {
        const isLargeDraw = seriesModel.pipelineContext.large;
        if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) {
            this._isLargeDraw = isLargeDraw;
            this._clear();
        }
    }

    private _renderNormal(
        seriesModel: BarSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        payload: Payload
    ): void {
        const group = this.group;
        const data = seriesModel.getData();
        const oldData = this._data;

        const coord = seriesModel.coordinateSystem;
        const baseAxis = coord.getBaseAxis();
        let isHorizontalOrRadial: boolean;

        if (coord.type === 'cartesian2d') {
            isHorizontalOrRadial = (baseAxis as Axis2D).isHorizontal();
        }
        else if (coord.type === 'polar') {
            isHorizontalOrRadial = baseAxis.dim === 'angle';
        }

        const animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;

        const realtimeSortCfg = shouldRealtimeSort(seriesModel, coord);

        if (realtimeSortCfg) {
            this._enableRealtimeSort(realtimeSortCfg, data, api);
        }

        const needsClip = seriesModel.get('clip', true) || realtimeSortCfg;
        const coordSysClipArea = getClipArea(coord, data);
        // If there is clipPath created in large mode. Remove it.
        group.removeClipPath();
        // We don't use clipPath in normal mode because we needs a perfect animation
        // And don't want the label are clipped.

        const roundCap = seriesModel.get('roundCap', true);

        const drawBackground = seriesModel.get('showBackground', true);
        const backgroundModel = seriesModel.getModel('backgroundStyle');
        const barBorderRadius = backgroundModel.get('borderRadius') || 0;

        const bgEls: BarView['_backgroundEls'] = [];
        const oldBgEls = this._backgroundEls;

        const isInitSort = payload && payload.isInitSort;
        const isChangeOrder = payload && payload.type === 'changeAxisOrder';

        function createBackground(dataIndex: number) {
            const bgLayout = getLayout[coord.type](data, dataIndex);
            const bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout);
            bgEl.useStyle(backgroundModel.getItemStyle());
            // Only cartesian2d support borderRadius.
            if (coord.type === 'cartesian2d') {
                (bgEl as Rect).setShape('r', barBorderRadius);
            }
            bgEls[dataIndex] = bgEl;
            return bgEl;
        };
        data.diff(oldData)
            .add(function (dataIndex) {
                const itemModel = data.getItemModel<BarDataItemOption>(dataIndex);
                const layout = getLayout[coord.type](data, dataIndex, itemModel);

                if (drawBackground) {
                    createBackground(dataIndex);
                }

                // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy".
                if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) {
                    return;
                }

                let isClipped = false;
                if (needsClip) {
                    // Clip will modify the layout params.
                    // And return a boolean to determine if the shape are fully clipped.
                    isClipped = clip[coord.type](coordSysClipArea, layout);
                }

                const el = elementCreator[coord.type](
                    seriesModel,
                    data,
                    dataIndex,
                    layout,
                    isHorizontalOrRadial,
                    animationModel,
                    baseAxis.model,
                    false,
                    roundCap
                );
                if (realtimeSortCfg) {
                    /**
                     * Force label animation because even if the element is
                     * ignored because it's clipped, it may not be clipped after
                     * changing order. Then, if not using forceLabelAnimation,
                     * the label animation was never started, in which case,
                     * the label will be the final value and doesn't have label
                     * animation.
                     */
                    (el as ECElement).forceLabelAnimation = true;
                }

                updateStyle(
                    el, data, dataIndex, itemModel, layout,
                    seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                );
                if (isInitSort) {
                    (el as Rect).attr({ shape: layout });
                }
                else if (realtimeSortCfg) {
                    updateRealtimeAnimation(
                        realtimeSortCfg,
                        animationModel,
                        el as Rect,
                        layout as LayoutRect,
                        dataIndex,
                        isHorizontalOrRadial,
                        false,
                        false
                    );
                }
                else {
                    initProps(el, {shape: layout} as any, seriesModel, dataIndex);
                }

                data.setItemGraphicEl(dataIndex, el);

                group.add(el);
                el.ignore = isClipped;
            })
            .update(function (newIndex, oldIndex) {
                const itemModel = data.getItemModel<BarDataItemOption>(newIndex);
                const layout = getLayout[coord.type](data, newIndex, itemModel);

                if (drawBackground) {
                    let bgEl: Rect | Sector;
                    if (oldBgEls.length === 0) {
                        bgEl = createBackground(oldIndex);
                    }
                    else {
                        bgEl = oldBgEls[oldIndex];
                        bgEl.useStyle(backgroundModel.getItemStyle());
                        // Only cartesian2d support borderRadius.
                        if (coord.type === 'cartesian2d') {
                            (bgEl as Rect).setShape('r', barBorderRadius);
                        }
                        bgEls[newIndex] = bgEl;
                    }
                    const bgLayout = getLayout[coord.type](data, newIndex);
                    const shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord);
                    updateProps(bgEl, { shape }, animationModel, newIndex);
                }

                let el = oldData.getItemGraphicEl(oldIndex) as BarPossiblePath;
                if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) {
                    group.remove(el);
                    return;
                }

                let isClipped = false;
                if (needsClip) {
                    isClipped = clip[coord.type](coordSysClipArea, layout);
                    if (isClipped) {
                        group.remove(el);
                    }
                }

                if (!el) {
                    el = elementCreator[coord.type](
                        seriesModel,
                        data,
                        newIndex,
                        layout,
                        isHorizontalOrRadial,
                        animationModel,
                        baseAxis.model,
                        !!el,
                        roundCap
                    );
                }
                else {
                    saveOldStyle(el);
                }

                if (realtimeSortCfg) {
                    (el as ECElement).forceLabelAnimation = true;
                }

                if (isChangeOrder) {
                    const textEl = el.getTextContent();
                    if (textEl) {
                        const labelInnerStore = labelInner(textEl);
                        if (labelInnerStore.prevValue != null) {
                            /**
                             * Set preValue to be value so that no new label
                             * should be started, otherwise, it will take a full
                             * `animationDurationUpdate` time to finish the
                             * animation, which is not expected.
                             */
                            labelInnerStore.prevValue = labelInnerStore.value;
                        }
                    }
                }
                // Not change anything if only order changed.
                // Especially not change label.
                else {
                    updateStyle(
                        el, data, newIndex, itemModel, layout,
                        seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                    );
                }

                if (isInitSort) {
                    (el as Rect).attr({ shape: layout });
                }
                else if (realtimeSortCfg) {
                    updateRealtimeAnimation(
                        realtimeSortCfg,
                        animationModel,
                        el as Rect,
                        layout as LayoutRect,
                        newIndex,
                        isHorizontalOrRadial,
                        true,
                        isChangeOrder
                    );
                }
                else {
                    updateProps(el, {
                        shape: layout
                    } as any, seriesModel, newIndex, null);
                }

                data.setItemGraphicEl(newIndex, el);
                el.ignore = isClipped;
                group.add(el);
            })
            .remove(function (dataIndex) {
                const el = oldData.getItemGraphicEl(dataIndex) as Path;
                el && removeElementWithFadeOut(el, seriesModel, dataIndex);
            })
            .execute();

        const bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group());
        bgGroup.removeAll();

        for (let i = 0; i < bgEls.length; ++i) {
            bgGroup.add(bgEls[i]);
        }
        group.add(bgGroup);
        this._backgroundEls = bgEls;

        this._data = data;
    }

    private _renderLarge(seriesModel: BarSeriesModel, ecModel: GlobalModel, api: ExtensionAPI): void {
        this._clear();
        createLarge(seriesModel, this.group);
        this._updateLargeClip(seriesModel);
    }

    private _incrementalRenderLarge(params: StageHandlerProgressParams, seriesModel: BarSeriesModel): void {
        this._removeBackground();
        createLarge(seriesModel, this.group, this._progressiveEls, true);
    }

    private _updateLargeClip(seriesModel: BarSeriesModel): void {
        // Use clipPath in large mode.
        const clipPath = seriesModel.get('clip', true)
            && createClipPath(seriesModel.coordinateSystem, false, seriesModel);
        const group = this.group;
        if (clipPath) {
            group.setClipPath(clipPath);
        }
        else {
            group.removeClipPath();
        }
    }

    private _enableRealtimeSort(
        realtimeSortCfg: RealtimeSortConfig,
        data: ReturnType<BarSeriesModel['getData']>,
        api: ExtensionAPI
    ): void {
        // If no data in the first frame, wait for data to initSort
        if (!data.count()) {
            return;
        }

        const baseAxis = realtimeSortCfg.baseAxis;

        if (this._isFirstFrame) {
            this._dispatchInitSort(data, realtimeSortCfg, api);
            this._isFirstFrame = false;
        }
        else {
            const orderMapping = (idx: number) => {
                const el = (data.getItemGraphicEl(idx) as Rect);
                const shape = el && el.shape;
                return (shape && (
                    // The result should be consistent with the initial sort by data value.
                    // Do not support the case that both positive and negative exist.
                    Math.abs(
                        baseAxis.isHorizontal()
                            ? shape.height
                            : shape.width
                    )
                // If data is NaN, shape.xxx may be NaN, so use || 0 here in case
                )) || 0;
            };
            this._onRendered = () => {
                this._updateSortWithinSameData(data, orderMapping, baseAxis, api);
            };
            api.getZr().on('rendered', this._onRendered);
        }
    }

    private _dataSort(
        data: SeriesData<BarSeriesModel, DefaultDataVisual>,
        baseAxis: Axis2D,
        orderMapping: OrderMapping
    ): OrdinalSortInfo {
        type SortValueInfo = {
            dataIndex: number,
            mappedValue: number,
            ordinalNumber: OrdinalNumber
        };
        const info: SortValueInfo[] = [];
        data.each(data.mapDimension(baseAxis.dim), (ordinalNumber: OrdinalNumber, dataIdx: number) => {
            let mappedValue = orderMapping(dataIdx);
            mappedValue = mappedValue == null ? NaN : mappedValue;
            info.push({
                dataIndex: dataIdx,
                mappedValue,
                ordinalNumber
            });
        });

        info.sort((a, b) => {
            // If NaN, it will be treated as min val.
            return b.mappedValue - a.mappedValue;
        });

        return {
            ordinalNumbers: map(info, item => item.ordinalNumber)
        };
    }

    private _isOrderChangedWithinSameData(
        data: SeriesData<BarSeriesModel, DefaultDataVisual>,
        orderMapping: OrderMapping,
        baseAxis: Axis2D
    ): boolean {
        const scale = baseAxis.scale as OrdinalScale;
        const ordinalDataDim = data.mapDimension(baseAxis.dim);

        let lastValue = Number.MAX_VALUE;
        for (let tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) {
            const rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum));
            const value = rawIdx < 0
                // If some tick have no bar, the tick will be treated as min.
                ? Number.MIN_VALUE
                // PENDING: if dataZoom on baseAxis exits, is it a performance issue?
                : orderMapping(data.indexOfRawIndex(rawIdx));
            if (value > lastValue) {
                return true;
            }
            lastValue = value;
        }
        return false;
    }

    /*
     * Consider the case when A and B changed order, whose representing
     * bars are both out of sight, we don't wish to trigger reorder action
     * as long as the order in the view doesn't change.
     */
    private _isOrderDifferentInView(
        orderInfo: OrdinalSortInfo,
        baseAxis: Axis2D
    ): boolean {
        const scale = baseAxis.scale as OrdinalScale;
        const extent = scale.getExtent();

        let tickNum = Math.max(0, extent[0]);
        const tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1);
        for (;tickNum <= tickMax; ++tickNum) {
            if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) {
                return true;
            }
        }
    }

    private _updateSortWithinSameData(
        data: SeriesData<BarSeriesModel, DefaultDataVisual>,
        orderMapping: OrderMapping,
        baseAxis: Axis2D,
        api: ExtensionAPI
    ) {
        if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) {
            return;
        }

        const sortInfo = this._dataSort(data, baseAxis, orderMapping);

        if (this._isOrderDifferentInView(sortInfo, baseAxis)) {
            this._removeOnRenderedListener(api);
            api.dispatchAction({
                type: 'changeAxisOrder',
                componentType: baseAxis.dim + 'Axis',
                axisId: baseAxis.index,
                sortInfo: sortInfo
            });
        }
    }

    private _dispatchInitSort(
        data: SeriesData<BarSeriesModel, DefaultDataVisual>,
        realtimeSortCfg: RealtimeSortConfig,
        api: ExtensionAPI
    ) {
        const baseAxis = realtimeSortCfg.baseAxis;
        const sortResult = this._dataSort(
            data,
            baseAxis,
            dataIdx => data.get(
                data.mapDimension(realtimeSortCfg.otherAxis.dim),
                dataIdx
            ) as number
        );
        api.dispatchAction({
            type: 'changeAxisOrder',
            componentType: baseAxis.dim + 'Axis',
            isInitSort: true,
            axisId: baseAxis.index,
            sortInfo: sortResult
        });
    }

    remove(ecModel: GlobalModel, api: ExtensionAPI) {
        this._clear(this._model);
        this._removeOnRenderedListener(api);
    }

    dispose(ecModel: GlobalModel, api: ExtensionAPI) {
        this._removeOnRenderedListener(api);
    }

    private _removeOnRenderedListener(api: ExtensionAPI) {
        if (this._onRendered) {
            api.getZr().off('rendered', this._onRendered);
            this._onRendered = null;
        }
    }

    private _clear(model?: SeriesModel): void {
        const group = this.group;
        const data = this._data;
        if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) {
            this._removeBackground();
            this._backgroundEls = [];

            data.eachItemGraphicEl(function (el: Path) {
                removeElementWithFadeOut(el, model, getECData(el).dataIndex);
            });
        }
        else {
            group.removeAll();
        }
        this._data = null;
        this._isFirstFrame = true;
    }

    private _removeBackground(): void {
        this.group.remove(this._backgroundGroup);
        this._backgroundGroup = null;
    }
}

interface Clipper {
    (coordSysBoundingRect: PolarCoordArea | CartesianCoordArea, layout: RectLayout | SectorLayout): boolean
}
const clip: {
    [key in 'cartesian2d' | 'polar']: Clipper
} = {
    cartesian2d(coordSysBoundingRect: CartesianCoordArea, layout: Rect['shape']) {
        const signWidth = layout.width < 0 ? -1 : 1;
        const signHeight = layout.height < 0 ? -1 : 1;
        // Needs positive width and height
        if (signWidth < 0) {
            layout.x += layout.width;
            layout.width = -layout.width;
        }
        if (signHeight < 0) {
            layout.y += layout.height;
            layout.height = -layout.height;
        }

        const coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width;
        const coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height;
        const x = mathMax(layout.x, coordSysBoundingRect.x);
        const x2 = mathMin(layout.x + layout.width, coordSysX2);
        const y = mathMax(layout.y, coordSysBoundingRect.y);
        const y2 = mathMin(layout.y + layout.height, coordSysY2);

        const xClipped = x2 < x;
        const yClipped = y2 < y;

        // When xClipped or yClipped, the element will be marked as `ignore`.
        // But we should also place the element at the edge of the coord sys bounding rect.
        // Because if data changed and the bar shows again, its transition animation
        // will begin at this place.
        layout.x = (xClipped && x > coordSysX2) ? x2 : x;
        layout.y = (yClipped && y > coordSysY2) ? y2 : y;
        layout.width = xClipped ? 0 : x2 - x;
        layout.height = yClipped ? 0 : y2 - y;

        // Reverse back
        if (signWidth < 0) {
            layout.x += layout.width;
            layout.width = -layout.width;
        }
        if (signHeight < 0) {
            layout.y += layout.height;
            layout.height = -layout.height;
        }

        return xClipped || yClipped;
    },

    polar(coordSysClipArea: PolarCoordArea, layout: Sector['shape']) {
        const signR = layout.r0 <= layout.r ? 1 : -1;
        // Make sure r is larger than r0
        if (signR < 0) {
            const tmp = layout.r;
            layout.r = layout.r0;
            layout.r0 = tmp;
        }

        const r = mathMin(layout.r, coordSysClipArea.r);
        const r0 = mathMax(layout.r0, coordSysClipArea.r0);

        layout.r = r;
        layout.r0 = r0;

        const clipped = r - r0 < 0;

        // Reverse back
        if (signR < 0) {
            const tmp = layout.r;
            layout.r = layout.r0;
            layout.r0 = tmp;
        }

        return clipped;
    }
};

interface ElementCreator {
    (
        seriesModel: BarSeriesModel, data: SeriesData, newIndex: number,
        layout: RectLayout | SectorLayout, isHorizontalOrRadial: boolean,
        animationModel: BarSeriesModel,
        axisModel: CartesianAxisModel | AngleAxisModel | RadiusAxisModel,
        isUpdate: boolean,
        roundCap?: boolean
    ): BarPossiblePath
}

const elementCreator: {
    [key in 'polar' | 'cartesian2d']: ElementCreator
} = {

    cartesian2d(
        seriesModel, data, newIndex, layout: RectLayout, isHorizontal,
        animationModel, axisModel, isUpdate, roundCap
    ) {
        const rect = new Rect({
            shape: extend({}, layout),
            z2: 1
        });
        (rect as any).__dataIndex = newIndex;

        rect.name = 'item';

        if (animationModel) {
            const rectShape = rect.shape;
            const animateProperty = isHorizontal ? 'height' : 'width' as 'width' | 'height';
            rectShape[animateProperty] = 0;
        }
        return rect;
    },

    polar(
        seriesModel, data, newIndex, layout: SectorLayout, isRadial: boolean,
        animationModel, axisModel, isUpdate, roundCap
    ) {
        const ShapeClass = (!isRadial && roundCap) ? Sausage : Sector;
        const sector = new ShapeClass({
            shape: layout,
            z2: 1
        });

        sector.name = 'item';

        const positionMap = createPolarPositionMapping(isRadial);
        sector.calculateTextPosition = createSectorCalculateTextPosition(positionMap, {
            isRoundCap: ShapeClass === Sausage
        });

        // Animation
        if (animationModel) {
            const sectorShape = sector.shape;
            const animateProperty = isRadial ? 'r' : 'endAngle' as 'r' | 'endAngle';
            const animateTarget = {} as SectorShape;
            sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
            animateTarget[animateProperty] = layout[animateProperty];
            (isUpdate ? updateProps : initProps)(sector, {
                shape: animateTarget
                // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue
            }, animationModel);
        }

        return sector;
    }
};

function shouldRealtimeSort(
    seriesModel: BarSeriesModel,
    coordSys: Cartesian2D | Polar
): RealtimeSortConfig {
    const realtimeSortOption = seriesModel.get('realtimeSort', true);
    const baseAxis = coordSys.getBaseAxis() as Axis2D;
    if (__DEV__) {
        if (realtimeSortOption) {
            if (baseAxis.type !== 'category') {
                warn('`realtimeSort` will not work because this bar series is not based on a category axis.');
            }
            if (coordSys.type !== 'cartesian2d') {
                warn('`realtimeSort` will not work because this bar series is not on cartesian2d.');
            }
        }
    }
    if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') {
        return {
            baseAxis: baseAxis as Axis2D,
            otherAxis: coordSys.getOtherAxis(baseAxis)
        };
    }
}

function updateRealtimeAnimation(
    realtimeSortCfg: RealtimeSortConfig,
    seriesAnimationModel: BarSeriesModel,
    el: Rect,
    layout: LayoutRect,
    newIndex: number,
    isHorizontal: boolean,
    isUpdate: boolean,
    isChangeOrder: boolean
) {
    let seriesTarget;
    let axisTarget;
    if (isHorizontal) {
        axisTarget = {
            x: layout.x,
            width: layout.width
        };
        seriesTarget = {
            y: layout.y,
            height: layout.height
        };
    }
    else {
        axisTarget = {
            y: layout.y,
            height: layout.height
        };
        seriesTarget = {
            x: layout.x,
            width: layout.width
        };
    }

    if (!isChangeOrder) {
        // Keep the original growth animation if only axis order changed.
        // Not start a new animation.
        (isUpdate ? updateProps : initProps)(el, {
            shape: seriesTarget
        }, seriesAnimationModel, newIndex, null);
    }

    const axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null;
    (isUpdate ? updateProps : initProps)(el, {
        shape: axisTarget
    }, axisAnimationModel, newIndex);
}

function checkPropertiesNotValid<T extends Record<string, any>>(obj: T, props: readonly (keyof T)[]) {
    for (let i = 0; i < props.length; i++) {
        if (!isFinite(obj[props[i]])) {
            return true;
        }
    }
    return false;
}


const rectPropties = ['x', 'y', 'width', 'height'] as const;
const polarPropties = ['cx', 'cy', 'r', 'startAngle', 'endAngle'] as const;
const isValidLayout: Record<'cartesian2d' | 'polar', (layout: RectLayout | SectorLayout) => boolean> = {
    cartesian2d(layout: RectLayout) {
        return !checkPropertiesNotValid(layout, rectPropties);
    },

    polar(layout: SectorLayout) {
        return !checkPropertiesNotValid(layout, polarPropties);
    }
} as const;

interface GetLayout {
    (data: SeriesData, dataIndex: number, itemModel?: Model<BarDataItemOption>): RectLayout | SectorLayout
}
const getLayout: {
    [key in 'cartesian2d' | 'polar']: GetLayout
} = {
    // itemModel is only used to get borderWidth, which is not needed
    // when calculating bar background layout.
    cartesian2d(data, dataIndex, itemModel?): RectLayout {
        const layout = data.getItemLayout(dataIndex) as RectLayout;
        const fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0;

        // fix layout with lineWidth
        const signX = layout.width > 0 ? 1 : -1;
        const signY = layout.height > 0 ? 1 : -1;
        return {
            x: layout.x + signX * fixedLineWidth / 2,
            y: layout.y + signY * fixedLineWidth / 2,
            width: layout.width - signX * fixedLineWidth,
            height: layout.height - signY * fixedLineWidth
        };
    },

    polar(data, dataIndex, itemModel?): SectorLayout {
        const layout = data.getItemLayout(dataIndex);
        return {
            cx: layout.cx,
            cy: layout.cy,
            r0: layout.r0,
            r: layout.r,
            startAngle: layout.startAngle,
            endAngle: layout.endAngle,
            clockwise: layout.clockwise
        } as SectorLayout;
    }
};

function isZeroOnPolar(layout: SectorLayout) {
    return layout.startAngle != null
        && layout.endAngle != null
        && layout.startAngle === layout.endAngle;
}

function createPolarPositionMapping(isRadial: boolean)
    : (position: PolarBarLabelPosition) => SectorTextPosition {
    return ((isRadial: boolean) => {
        const arcOrAngle = isRadial ? 'Arc' : 'Angle';
        return (position: PolarBarLabelPosition) => {
            switch (position) {
                case 'start':
                case 'insideStart':
                case 'end':
                case 'insideEnd':
                    return position + arcOrAngle as SectorTextPosition;
                default:
                    return position;
            }
        };
    })(isRadial);
}

function updateStyle(
    el: BarPossiblePath,
    data: SeriesData, dataIndex: number,
    itemModel: Model<BarDataItemOption>,
    layout: RectLayout | SectorLayout,
    seriesModel: BarSeriesModel,
    isHorizontalOrRadial: boolean,
    isPolar: boolean
) {
    const style = data.getItemVisual(dataIndex, 'style');

    if (!isPolar) {
        (el as Rect).setShape('r', itemModel.get(['itemStyle', 'borderRadius']) || 0);
    }

    el.useStyle(style);

    const cursorStyle = itemModel.getShallow('cursor');
    cursorStyle && (el as Path).attr('cursor', cursorStyle);

    const labelPositionOutside = isPolar
        ? (isHorizontalOrRadial
            ? ((layout as SectorLayout).r >= (layout as SectorLayout).r0 ? 'endArc' : 'startArc')
            : ((layout as SectorLayout).endAngle >= (layout as SectorLayout).startAngle
                ? 'endAngle'
                : 'startAngle'
            )
        )
        : (isHorizontalOrRadial
            ? ((layout as RectLayout).height >= 0 ? 'bottom' : 'top')
            : ((layout as RectLayout).width >= 0 ? 'right' : 'left'));

    const labelStatesModels = getLabelStatesModels(itemModel);

    setLabelStyle(
        el, labelStatesModels,
        {
            labelFetcher: seriesModel,
            labelDataIndex: dataIndex,
            defaultText: getDefaultLabel(seriesModel.getData(), dataIndex),
            inheritColor: style.fill as ColorString,
            defaultOpacity: style.opacity,
            defaultOutsidePosition: labelPositionOutside as BuiltinTextPosition
        }
    );

    const label = el.getTextContent();
    if (isPolar && label) {
        const position = itemModel.get(['label', 'position']);
        el.textConfig.inside = position === 'middle' ? true : null;
        setSectorTextRotation(
            el as Sector,
            position === 'outside' ? labelPositionOutside : position,
            createPolarPositionMapping(isHorizontalOrRadial),
            itemModel.get(['label', 'rotate'])
        );
    }

    setLabelValueAnimation(
        label,
        labelStatesModels,
        seriesModel.getRawValue(dataIndex) as ParsedValue,
        (value: number) => getDefaultInterpolatedLabel(data, value)
    );

    const emphasisModel = itemModel.getModel(['emphasis']);
    toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled'));
    setStatesStylesFromModel(el, itemModel);

    if (isZeroOnPolar(layout as SectorLayout)) {
        el.style.fill = 'none';
        el.style.stroke = 'none';
        each(el.states, (state) => {
            if (state.style) {
                state.style.fill = state.style.stroke = 'none';
            }
        });
    }
}

// In case width or height are too small.
function getLineWidth(
    itemModel: Model<BarDataItemOption>,
    rawLayout: RectLayout
) {
    // Has no border.
    const borderColor = itemModel.get(['itemStyle', 'borderColor']);
    if (!borderColor || borderColor === 'none') {
        return 0;
    }
    const lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0;
    // width or height may be NaN for empty data
    const width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width);
    const height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height);
    return Math.min(lineWidth, width, height);
}

class LagePathShape {
    points: ArrayLike<number>;
}
interface LargePathProps extends PathProps {
    shape?: LagePathShape
}
class LargePath extends Path<LargePathProps> {
    type = 'largeBar';

    shape: LagePathShape;

    baseDimIdx: number;
    largeDataIndices: ArrayLike<number>;
    barWidth: number;

    constructor(opts?: LargePathProps) {
        super(opts);
    }

    getDefaultShape() {
        return new LagePathShape();
    }

    buildPath(ctx: CanvasRenderingContext2D, shape: LagePathShape) {
        // Drawing lines is more efficient than drawing
        // a whole line or drawing rects.
        const points = shape.points;
        const baseDimIdx = this.baseDimIdx;
        const valueDimIdx = 1 - this.baseDimIdx;
        const startPoint = [];
        const size = [];
        const barWidth = this.barWidth;

        for (let i = 0; i < points.length; i += 3) {
            size[baseDimIdx] = barWidth;
            size[valueDimIdx] = points[i + 2];
            startPoint[baseDimIdx] = points[i + baseDimIdx];
            startPoint[valueDimIdx] = points[i + valueDimIdx];
            ctx.rect(startPoint[0], startPoint[1], size[0], size[1]);
        }
    }
}

function createLarge(
    seriesModel: BarSeriesModel,
    group: Group,
    progressiveEls?: Element[],
    incremental?: boolean
) {
    // TODO support polar
    const data = seriesModel.getData();
    const baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;

    const largeDataIndices = data.getLayout('largeDataIndices');
    const barWidth = data.getLayout('size');

    const backgroundModel = seriesModel.getModel('backgroundStyle');
    const bgPoints = data.getLayout('largeBackgroundPoints');

    if (bgPoints) {
        const bgEl = new LargePath({
            shape: {
                points: bgPoints
            },
            incremental: !!incremental,
            silent: true,
            z2: 0
        });
        bgEl.baseDimIdx = baseDimIdx;
        bgEl.largeDataIndices = largeDataIndices;
        bgEl.barWidth = barWidth;
        bgEl.useStyle(backgroundModel.getItemStyle());
        group.add(bgEl);

        progressiveEls && progressiveEls.push(bgEl);
    }

    const el = new LargePath({
        shape: {points: data.getLayout('largePoints')},
        incremental: !!incremental,
        ignoreCoarsePointer: true,
        z2: 1
    });
    el.baseDimIdx = baseDimIdx;
    el.largeDataIndices = largeDataIndices;
    el.barWidth = barWidth;
    group.add(el);
    el.useStyle(data.getVisual('style'));

    // Enable tooltip and user mouse/touch event handlers.
    getECData(el).seriesIndex = seriesModel.seriesIndex;

    if (!seriesModel.get('silent')) {
        el.on('mousedown', largePathUpdateDataIndex);
        el.on('mousemove', largePathUpdateDataIndex);
    }
    progressiveEls && progressiveEls.push(el);
}

// Use throttle to avoid frequently traverse to find dataIndex.
const largePathUpdateDataIndex = throttle(function (this: LargePath, event: ZRElementEvent) {
    const largePath = this;
    const dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
    getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null;
}, 30, false);

function largePathFindDataIndex(largePath: LargePath, x: number, y: number) {
    const baseDimIdx = largePath.baseDimIdx;
    const valueDimIdx = 1 - baseDimIdx;
    const points = largePath.shape.points;
    const largeDataIndices = largePath.largeDataIndices;
    const startPoint = [];
    const size = [];
    const barWidth = largePath.barWidth;

    for (let i = 0, len = points.length / 3; i < len; i++) {
        const ii = i * 3;
        size[baseDimIdx] = barWidth;
        size[valueDimIdx] = points[ii + 2];
        startPoint[baseDimIdx] = points[ii + baseDimIdx];
        startPoint[valueDimIdx] = points[ii + valueDimIdx];
        if (size[valueDimIdx] < 0) {
            startPoint[valueDimIdx] += size[valueDimIdx];
            size[valueDimIdx] = -size[valueDimIdx];
        }

        if (x >= startPoint[0] && x <= startPoint[0] + size[0]
            && y >= startPoint[1] && y <= startPoint[1] + size[1]
        ) {
            return largeDataIndices[i];
        }
    }

    return -1;
}

function createBackgroundShape(
    isHorizontalOrRadial: boolean,
    layout: SectorLayout | RectLayout,
    coord: CoordSysOfBar
): SectorShape | RectShape {
    if (isCoordinateSystemType<Cartesian2D>(coord, 'cartesian2d')) {
        const rectShape = layout as RectShape;
        const coordLayout = coord.getArea();
        return {
            x: isHorizontalOrRadial ? rectShape.x : coordLayout.x,
            y: isHorizontalOrRadial ? coordLayout.y : rectShape.y,
            width: isHorizontalOrRadial ? rectShape.width : coordLayout.width,
            height: isHorizontalOrRadial ? coordLayout.height : rectShape.height
        } as RectShape;
    }
    else {
        const coordLayout = coord.getArea();
        const sectorShape = layout as SectorShape;
        return {
            cx: coordLayout.cx,
            cy: coordLayout.cy,
            r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0,
            r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r,
            startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0,
            endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2
        } as SectorShape;
    }
}

function createBackgroundEl(
    coord: CoordSysOfBar,
    isHorizontalOrRadial: boolean,
    layout: SectorLayout | RectLayout
): Rect | Sector {
    const ElementClz = coord.type === 'polar' ? Sector : Rect;
    return new ElementClz({
        shape: createBackgroundShape(isHorizontalOrRadial, layout, coord) as any,
        silent: true,
        z2: 0
    });
}

export default BarView;
