/*
* 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 ChartView from '../../view/Chart';
import * as graphic from '../../util/graphic';
import { setStatesStylesFromModel } from '../../util/states';
import Path, { PathProps } from 'zrender/src/graphic/Path';
import {createClipPath} from '../helper/createClipPathFromCoordSys';
import CandlestickSeriesModel, { CandlestickDataItemOption } from './CandlestickSeries';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { StageHandlerProgressParams } from '../../util/types';
import SeriesData from '../../data/SeriesData';
import {CandlestickItemLayout} from './candlestickLayout';
import { CoordinateSystemClipArea } from '../../coord/CoordinateSystem';
import Model from '../../model/Model';
import { saveOldStyle } from '../../animation/basicTransition';
import Element from 'zrender/src/Element';

const SKIP_PROPS = ['color', 'borderColor'] as const;

class CandlestickView extends ChartView {

    static readonly type = 'candlestick';
    readonly type = CandlestickView.type;

    private _isLargeDraw: boolean;

    private _data: SeriesData;

    private _progressiveEls: Element[];

    render(seriesModel: CandlestickSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
        // If there is clipPath created in large mode. Remove it.
        this.group.removeClipPath();
        // Clear previously rendered progressive elements.
        this._progressiveEls = null;

        this._updateDrawMode(seriesModel);

        this._isLargeDraw
            ? this._renderLarge(seriesModel)
            : this._renderNormal(seriesModel);
    }

    incrementalPrepareRender(seriesModel: CandlestickSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
        this._clear();
        this._updateDrawMode(seriesModel);
    }

    incrementalRender(
        params: StageHandlerProgressParams,
        seriesModel: CandlestickSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI
    ) {
        this._progressiveEls = [];
        this._isLargeDraw
             ? this._incrementalRenderLarge(params, seriesModel)
             : this._incrementalRenderNormal(params, seriesModel);
    }

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

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

    _renderNormal(seriesModel: CandlestickSeriesModel) {
        const data = seriesModel.getData();
        const oldData = this._data;
        const group = this.group;
        const isSimpleBox = data.getLayout('isSimpleBox');

        const needsClip = seriesModel.get('clip', true);
        const coord = seriesModel.coordinateSystem;
        const clipArea = coord.getArea && coord.getArea();

        // There is no old data only when first rendering or switching from
        // stream mode to normal mode, where previous elements should be removed.
        if (!this._data) {
            group.removeAll();
        }

        data.diff(oldData)
            .add(function (newIdx) {
                if (data.hasValue(newIdx)) {
                    const itemLayout = data.getItemLayout(newIdx) as CandlestickItemLayout;

                    if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
                        return;
                    }

                    const el = createNormalBox(itemLayout, newIdx, true);
                    graphic.initProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);

                    setBoxCommon(el, data, newIdx, isSimpleBox);

                    group.add(el);

                    data.setItemGraphicEl(newIdx, el);
                }
            })
            .update(function (newIdx, oldIdx) {
                let el = oldData.getItemGraphicEl(oldIdx) as NormalBoxPath;

                // Empty data
                if (!data.hasValue(newIdx)) {
                    group.remove(el);
                    return;
                }

                const itemLayout = data.getItemLayout(newIdx) as CandlestickItemLayout;
                if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) {
                    group.remove(el);
                    return;
                }

                if (!el) {
                    el = createNormalBox(itemLayout, newIdx);
                }
                else {
                    graphic.updateProps(el, {
                        shape: {
                            points: itemLayout.ends
                        }
                    }, seriesModel, newIdx);

                    saveOldStyle(el);
                }

                setBoxCommon(el, data, newIdx, isSimpleBox);

                group.add(el);
                data.setItemGraphicEl(newIdx, el);
            })
            .remove(function (oldIdx) {
                const el = oldData.getItemGraphicEl(oldIdx);
                el && group.remove(el);
            })
            .execute();

        this._data = data;
    }

    _renderLarge(seriesModel: CandlestickSeriesModel) {
        this._clear();

        createLarge(seriesModel, this.group);

        const clipPath = seriesModel.get('clip', true)
            ? createClipPath(seriesModel.coordinateSystem, false, seriesModel)
            : null;
        if (clipPath) {
            this.group.setClipPath(clipPath);
        }
        else {
            this.group.removeClipPath();
        }

    }

    _incrementalRenderNormal(params: StageHandlerProgressParams, seriesModel: CandlestickSeriesModel) {
        const data = seriesModel.getData();
        const isSimpleBox = data.getLayout('isSimpleBox');

        let dataIndex;
        while ((dataIndex = params.next()) != null) {
            const itemLayout = data.getItemLayout(dataIndex) as CandlestickItemLayout;
            const el = createNormalBox(itemLayout, dataIndex);
            setBoxCommon(el, data, dataIndex, isSimpleBox);

            el.incremental = true;
            this.group.add(el);

            this._progressiveEls.push(el);
        }
    }

    _incrementalRenderLarge(params: StageHandlerProgressParams, seriesModel: CandlestickSeriesModel) {
        createLarge(seriesModel, this.group, this._progressiveEls, true);
    }

    remove(ecModel: GlobalModel) {
        this._clear();
    }

    _clear() {
        this.group.removeAll();
        this._data = null;
    }
}

class NormalBoxPathShape {
    points: number[][];
}

interface NormalBoxPathProps extends PathProps {
    shape?: Partial<NormalBoxPathShape>
}

class NormalBoxPath extends Path<NormalBoxPathProps> {

    readonly type = 'normalCandlestickBox';

    shape: NormalBoxPathShape;

    __simpleBox: boolean;

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

    getDefaultShape() {
        return new NormalBoxPathShape();
    }

    buildPath(ctx: CanvasRenderingContext2D, shape: NormalBoxPathShape) {
        const ends = shape.points;

        if (this.__simpleBox) {
            ctx.moveTo(ends[4][0], ends[4][1]);
            ctx.lineTo(ends[6][0], ends[6][1]);
        }
        else {
            ctx.moveTo(ends[0][0], ends[0][1]);
            ctx.lineTo(ends[1][0], ends[1][1]);
            ctx.lineTo(ends[2][0], ends[2][1]);
            ctx.lineTo(ends[3][0], ends[3][1]);
            ctx.closePath();

            ctx.moveTo(ends[4][0], ends[4][1]);
            ctx.lineTo(ends[5][0], ends[5][1]);
            ctx.moveTo(ends[6][0], ends[6][1]);
            ctx.lineTo(ends[7][0], ends[7][1]);
        }
    }
}


function createNormalBox(itemLayout: CandlestickItemLayout, dataIndex: number, isInit?: boolean) {
    const ends = itemLayout.ends;
    return new NormalBoxPath({
        shape: {
            points: isInit
                ? transInit(ends, itemLayout)
                : ends
        },
        z2: 100
    });
}

function isNormalBoxClipped(clipArea: CoordinateSystemClipArea, itemLayout: CandlestickItemLayout) {
    let clipped = true;
    for (let i = 0; i < itemLayout.ends.length; i++) {
        // If any point are in the region.
        if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) {
            clipped = false;
            break;
        }
    }
    return clipped;
}

function setBoxCommon(el: NormalBoxPath, data: SeriesData, dataIndex: number, isSimpleBox?: boolean) {
    const itemModel = data.getItemModel(dataIndex) as Model<CandlestickDataItemOption>;

    el.useStyle(data.getItemVisual(dataIndex, 'style'));
    el.style.strokeNoScale = true;

    el.__simpleBox = isSimpleBox;

    setStatesStylesFromModel(el, itemModel);
}

function transInit(points: number[][], itemLayout: CandlestickItemLayout) {
    return zrUtil.map(points, function (point) {
        point = point.slice();
        point[1] = itemLayout.initBaseline;
        return point;
    });
}



class LargeBoxPathShape {
    points: ArrayLike<number>;
}

interface LargeBoxPathProps extends PathProps {
    shape?: Partial<LargeBoxPathShape>
    __sign?: number
}

class LargeBoxPath extends Path {
    readonly type = 'largeCandlestickBox';

    shape: LargeBoxPathShape;

    __sign: number;

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

    getDefaultShape() {
        return new LargeBoxPathShape();
    }

    buildPath(ctx: CanvasRenderingContext2D, shape: LargeBoxPathShape) {
        // Drawing lines is more efficient than drawing
        // a whole line or drawing rects.
        const points = shape.points;
        for (let i = 0; i < points.length;) {
            if (this.__sign === points[i++]) {
                const x = points[i++];
                ctx.moveTo(x, points[i++]);
                ctx.lineTo(x, points[i++]);
            }
            else {
                i += 3;
            }
        }
    }
}

function createLarge(
    seriesModel: CandlestickSeriesModel,
    group: graphic.Group,
    progressiveEls?: Element[],
    incremental?: boolean
) {
    const data = seriesModel.getData();
    const largePoints = data.getLayout('largePoints');

    const elP = new LargeBoxPath({
        shape: {points: largePoints},
        __sign: 1,
        ignoreCoarsePointer: true
    });
    group.add(elP);
    const elN = new LargeBoxPath({
        shape: {points: largePoints},
        __sign: -1,
        ignoreCoarsePointer: true
    });
    group.add(elN);
    const elDoji = new LargeBoxPath({
        shape: {points: largePoints},
        __sign: 0,
        ignoreCoarsePointer: true
    });
    group.add(elDoji);

    setLargeStyle(1, elP, seriesModel, data);
    setLargeStyle(-1, elN, seriesModel, data);
    setLargeStyle(0, elDoji, seriesModel, data);

    if (incremental) {
        elP.incremental = true;
        elN.incremental = true;
    }

    if (progressiveEls) {
        progressiveEls.push(elP, elN);
    }
}

function setLargeStyle(sign: number, el: LargeBoxPath, seriesModel: CandlestickSeriesModel, data: SeriesData) {
    // TODO put in visual?
    let borderColor = seriesModel.get(['itemStyle', sign > 0 ? 'borderColor' : 'borderColor0'])
        // Use color for border color by default.
        || seriesModel.get(['itemStyle', sign > 0 ? 'color' : 'color0']);
    if (sign === 0) {
        borderColor = seriesModel.get(['itemStyle', 'borderColorDoji']);
    }

    // Color must be excluded.
    // Because symbol provide setColor individually to set fill and stroke
    const itemStyle = seriesModel.getModel('itemStyle').getItemStyle(SKIP_PROPS);

    el.useStyle(itemStyle);
    el.style.fill = null;
    el.style.stroke = borderColor;
}



export default CandlestickView;
