/*
* 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 PointerPath from './PointerPath';
import * as graphic from '../../util/graphic';
import { setStatesStylesFromModel, toggleHoverEmphasis } from '../../util/states';
import {createTextStyle, setLabelValueAnimation, animateLabelValue} from '../../label/labelStyle';
import ChartView from '../../view/Chart';
import {parsePercent, round, linearMap} from '../../util/number';
import GaugeSeriesModel, { GaugeDataItemOption } from './GaugeSeries';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { ColorString, ECElement } from '../../util/types';
import SeriesData from '../../data/SeriesData';
import Sausage from '../../util/shape/sausage';
import {createSymbol} from '../../util/symbol';
import ZRImage from 'zrender/src/graphic/Image';
import { extend, isFunction, isString, isNumber, each } from 'zrender/src/core/util';
import {setCommonECData} from '../../util/innerStore';
import { normalizeArcAngles } from 'zrender/src/core/PathProxy';

type ECSymbol = ReturnType<typeof createSymbol>;

interface PosInfo {
    cx: number
    cy: number
    r: number
}

function parsePosition(seriesModel: GaugeSeriesModel, api: ExtensionAPI): PosInfo {
    const center = seriesModel.get('center');
    const width = api.getWidth();
    const height = api.getHeight();
    const size = Math.min(width, height);
    const cx = parsePercent(center[0], api.getWidth());
    const cy = parsePercent(center[1], api.getHeight());
    const r = parsePercent(seriesModel.get('radius'), size / 2);

    return {
        cx: cx,
        cy: cy,
        r: r
    };
}

function formatLabel(value: number, labelFormatter: string | ((value: number) => string)): string {
    let label = value == null ? '' : (value + '');
    if (labelFormatter) {
        if (isString(labelFormatter)) {
            label = labelFormatter.replace('{value}', label);
        }
        else if (isFunction(labelFormatter)) {
            label = labelFormatter(value);
        }
    }

    return label;
}

class GaugeView extends ChartView {
    static type = 'gauge' as const;
    type = GaugeView.type;

    private _data: SeriesData;
    private _progressEls: graphic.Path[];

    private _titleEls: graphic.Text[];
    private _detailEls: graphic.Text[];

    render(seriesModel: GaugeSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {

        this.group.removeAll();

        const colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']);
        const posInfo = parsePosition(seriesModel, api);

        this._renderMain(
            seriesModel, ecModel, api, colorList, posInfo
        );

        this._data = seriesModel.getData();
    }

    dispose() {}

    _renderMain(
        seriesModel: GaugeSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        colorList: [number, ColorString][],
        posInfo: PosInfo
    ) {
        const group = this.group;
        const clockwise = seriesModel.get('clockwise');
        let startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
        let endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;
        const axisLineModel = seriesModel.getModel('axisLine');

        const roundCap = axisLineModel.get('roundCap');
        const MainPath = roundCap ? Sausage : graphic.Sector;

        const showAxis = axisLineModel.get('show');
        const lineStyleModel = axisLineModel.getModel('lineStyle');
        const axisLineWidth = lineStyleModel.get('width');

        const angles = [startAngle, endAngle];
        normalizeArcAngles(angles, !clockwise);
        startAngle = angles[0];
        endAngle = angles[1];
        const angleRangeSpan = endAngle - startAngle;

        let prevEndAngle = startAngle;

        const sectors: (Sausage | graphic.Sector)[] = [];
        for (let i = 0; showAxis && i < colorList.length; i++) {
            // Clamp
            const percent = Math.min(Math.max(colorList[i][0], 0), 1);
            endAngle = startAngle + angleRangeSpan * percent;
            const sector = new MainPath({
                shape: {
                    startAngle: prevEndAngle,
                    endAngle: endAngle,
                    cx: posInfo.cx,
                    cy: posInfo.cy,
                    clockwise: clockwise,
                    r0: posInfo.r - axisLineWidth,
                    r: posInfo.r
                },
                silent: true
            });

            sector.setStyle({
                fill: colorList[i][1]
            });

            sector.setStyle(lineStyleModel.getLineStyle(
                // Because we use sector to simulate arc
                // so the properties for stroking are useless
                ['color', 'width']
            ));

            sectors.push(sector);

            prevEndAngle = endAngle;
        }

        sectors.reverse();
        each(sectors, sector => group.add(sector));

        const getColor = function (percent: number) {
            // Less than 0
            if (percent <= 0) {
                return colorList[0][1];
            }
            let i;
            for (i = 0; i < colorList.length; i++) {
                if (colorList[i][0] >= percent
                    && (i === 0 ? 0 : colorList[i - 1][0]) < percent
                ) {
                    return colorList[i][1];
                }
            }
            // More than 1
            return colorList[i - 1][1];
        };

        this._renderTicks(
            seriesModel, ecModel, api, getColor, posInfo,
            startAngle, endAngle, clockwise, axisLineWidth
        );

        this._renderTitleAndDetail(
            seriesModel, ecModel, api, getColor, posInfo
        );

        this._renderAnchor(seriesModel, posInfo);

        this._renderPointer(
            seriesModel, ecModel, api, getColor, posInfo,
            startAngle, endAngle, clockwise, axisLineWidth
        );
    }

    _renderTicks(
        seriesModel: GaugeSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        getColor: (percent: number) => ColorString,
        posInfo: PosInfo,
        startAngle: number,
        endAngle: number,
        clockwise: boolean,
        axisLineWidth: number
    ) {
        const group = this.group;
        const cx = posInfo.cx;
        const cy = posInfo.cy;
        const r = posInfo.r;

        const minVal = +seriesModel.get('min');
        const maxVal = +seriesModel.get('max');

        const splitLineModel = seriesModel.getModel('splitLine');
        const tickModel = seriesModel.getModel('axisTick');
        const labelModel = seriesModel.getModel('axisLabel');

        const splitNumber = seriesModel.get('splitNumber');
        const subSplitNumber = tickModel.get('splitNumber');

        const splitLineLen = parsePercent(
            splitLineModel.get('length'), r
        );
        const tickLen = parsePercent(
            tickModel.get('length'), r
        );

        let angle = startAngle;
        const step = (endAngle - startAngle) / splitNumber;
        const subStep = step / subSplitNumber;

        const splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
        const tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();

        const splitLineDistance = splitLineModel.get('distance');

        let unitX;
        let unitY;

        for (let i = 0; i <= splitNumber; i++) {
            unitX = Math.cos(angle);
            unitY = Math.sin(angle);
            // Split line
            if (splitLineModel.get('show')) {
                const distance = splitLineDistance ? splitLineDistance + axisLineWidth : axisLineWidth;
                const splitLine = new graphic.Line({
                    shape: {
                        x1: unitX * (r - distance) + cx,
                        y1: unitY * (r - distance) + cy,
                        x2: unitX * (r - splitLineLen - distance) + cx,
                        y2: unitY * (r - splitLineLen - distance) + cy
                    },
                    style: splitLineStyle,
                    silent: true
                });
                if (splitLineStyle.stroke === 'auto') {
                    splitLine.setStyle({
                        stroke: getColor(i / splitNumber)
                    });
                }

                group.add(splitLine);
            }

            // Label
            if (labelModel.get('show')) {
                const distance = labelModel.get('distance') + splitLineDistance;

                const label = formatLabel(
                    round(i / splitNumber * (maxVal - minVal) + minVal),
                    labelModel.get('formatter')
                );
                const autoColor = getColor(i / splitNumber);
                const textStyleX = unitX * (r - splitLineLen - distance) + cx;
                const textStyleY = unitY * (r - splitLineLen - distance) + cy;

                const rotateType = labelModel.get('rotate');
                let rotate = 0;
                if (rotateType === 'radial') {
                    rotate = -angle + 2 * Math.PI;
                    if (rotate > Math.PI / 2) {
                        rotate += Math.PI;
                    }
                }
                else if (rotateType === 'tangential') {
                    rotate = -angle - Math.PI / 2;
                }
                else if (isNumber(rotateType)) {
                    rotate = rotateType * Math.PI / 180;
                }

                if (rotate === 0) {
                    group.add(new graphic.Text({
                        style: createTextStyle(labelModel, {
                            text: label,
                            x: textStyleX,
                            y: textStyleY,
                            verticalAlign: unitY < -0.8 ? 'top' : (unitY > 0.8 ? 'bottom' : 'middle'),
                            align: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
                        }, {
                            inheritColor: autoColor
                        }),
                        silent: true
                    }));
                }
                else {
                    group.add(new graphic.Text({
                        style: createTextStyle(labelModel, {
                            text: label,
                            x: textStyleX,
                            y: textStyleY,
                            verticalAlign: 'middle',
                            align: 'center'
                        }, {
                            inheritColor: autoColor
                        }),
                        silent: true,
                        originX: textStyleX,
                        originY: textStyleY,
                        rotation: rotate
                    }));
                }
            }

            // Axis tick
            if (tickModel.get('show') && i !== splitNumber) {
                let distance = tickModel.get('distance');
                distance = distance ? distance + axisLineWidth : axisLineWidth;

                for (let j = 0; j <= subSplitNumber; j++) {
                    unitX = Math.cos(angle);
                    unitY = Math.sin(angle);
                    const tickLine = new graphic.Line({
                        shape: {
                            x1: unitX * (r - distance) + cx,
                            y1: unitY * (r - distance) + cy,
                            x2: unitX * (r - tickLen - distance) + cx,
                            y2: unitY * (r - tickLen - distance) + cy
                        },
                        silent: true,
                        style: tickLineStyle
                    });

                    if (tickLineStyle.stroke === 'auto') {
                        tickLine.setStyle({
                            stroke: getColor((i + j / subSplitNumber) / splitNumber)
                        });
                    }

                    group.add(tickLine);
                    angle += subStep;
                }
                angle -= subStep;
            }
            else {
                angle += step;
            }
        }
    }

    _renderPointer(
        seriesModel: GaugeSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        getColor: (percent: number) => ColorString,
        posInfo: PosInfo,
        startAngle: number,
        endAngle: number,
        clockwise: boolean,
        axisLineWidth: number
    ) {

        const group = this.group;
        const oldData = this._data;
        const oldProgressData = this._progressEls;
        const progressList = [] as graphic.Path[];

        const showPointer = seriesModel.get(['pointer', 'show']);
        const progressModel = seriesModel.getModel('progress');
        const showProgress = progressModel.get('show');

        const data = seriesModel.getData();
        const valueDim = data.mapDimension('value');
        const minVal = +seriesModel.get('min');
        const maxVal = +seriesModel.get('max');
        const valueExtent = [minVal, maxVal];
        const angleExtent = [startAngle, endAngle];

        function createPointer(idx: number, angle: number) {
            const itemModel = data.getItemModel<GaugeDataItemOption>(idx);
            const pointerModel = itemModel.getModel('pointer');
            const pointerWidth = parsePercent(pointerModel.get('width'), posInfo.r);
            const pointerLength = parsePercent(pointerModel.get('length'), posInfo.r);
            const pointerStr = seriesModel.get(['pointer', 'icon']);
            const pointerOffset = pointerModel.get('offsetCenter');
            const pointerOffsetX = parsePercent(pointerOffset[0], posInfo.r);
            const pointerOffsetY = parsePercent(pointerOffset[1], posInfo.r);
            const pointerKeepAspect = pointerModel.get('keepAspect');

            let pointer;
            // not exist icon type will be set 'rect'
            if (pointerStr) {
                pointer = createSymbol(
                    pointerStr,
                    pointerOffsetX - pointerWidth / 2,
                    pointerOffsetY - pointerLength,
                    pointerWidth,
                    pointerLength,
                    null,
                    pointerKeepAspect
                ) as graphic.Path;
            }
            else {
                pointer = new PointerPath({
                    shape: {
                        angle: -Math.PI / 2,
                        width: pointerWidth,
                        r: pointerLength,
                        x: pointerOffsetX,
                        y: pointerOffsetY
                    }
                });
            }
            pointer.rotation = -(angle + Math.PI / 2);
            pointer.x = posInfo.cx;
            pointer.y = posInfo.cy;
            return pointer;
        }

        function createProgress(idx: number, endAngle: number) {
            const roundCap = progressModel.get('roundCap');
            const ProgressPath = roundCap ? Sausage : graphic.Sector;

            const isOverlap = progressModel.get('overlap');
            const progressWidth = isOverlap ? progressModel.get('width') : axisLineWidth / data.count();
            const r0 = isOverlap ? posInfo.r - progressWidth : posInfo.r - (idx + 1) * progressWidth;
            const r = isOverlap ? posInfo.r : posInfo.r - idx * progressWidth;
            const progress = new ProgressPath({
                shape: {
                    startAngle: startAngle,
                    endAngle: endAngle,
                    cx: posInfo.cx,
                    cy: posInfo.cy,
                    clockwise: clockwise,
                    r0: r0,
                    r: r
                }
            });
            isOverlap && (progress.z2 = maxVal - (data.get(valueDim, idx) as number) % maxVal);
            return progress;
        }

        if (showProgress || showPointer) {
            data.diff(oldData)
                .add(function (idx) {
                    const val = data.get(valueDim, idx) as number;
                    if (showPointer) {
                        const pointer = createPointer(idx, startAngle);
                        // TODO hide pointer on NaN value?
                        graphic.initProps(pointer, {
                            rotation: -(
                                (isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true))
                                + Math.PI / 2
                            )
                        }, seriesModel);
                        group.add(pointer);
                        data.setItemGraphicEl(idx, pointer);
                    }

                    if (showProgress) {
                        const progress = createProgress(idx, startAngle) as graphic.Sector;
                        const isClip = progressModel.get('clip');
                        graphic.initProps(progress, {
                            shape: {
                                endAngle: linearMap(val, valueExtent, angleExtent, isClip)
                            }
                        }, seriesModel);
                        group.add(progress);
                        // Add data index and series index for indexing the data by element
                        // Useful in tooltip
                        setCommonECData(seriesModel.seriesIndex, data.dataType, idx, progress);
                        progressList[idx] = progress;
                    }
                })
                .update(function (newIdx, oldIdx) {
                    const val = data.get(valueDim, newIdx) as number;
                    if (showPointer) {
                        const previousPointer = oldData.getItemGraphicEl(oldIdx) as PointerPath;
                        const previousRotate = previousPointer ? previousPointer.rotation : startAngle;
                        const pointer = createPointer(newIdx, previousRotate);
                        pointer.rotation = previousRotate;
                        graphic.updateProps(pointer, {
                            rotation: -(
                                (isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true))
                                    + Math.PI / 2
                            )
                        }, seriesModel);
                        group.add(pointer);
                        data.setItemGraphicEl(newIdx, pointer);
                    }

                    if (showProgress) {
                        const previousProgress = oldProgressData[oldIdx];
                        const previousEndAngle = previousProgress ? previousProgress.shape.endAngle : startAngle;
                        const progress = createProgress(newIdx, previousEndAngle) as graphic.Sector;
                        const isClip = progressModel.get('clip');
                        graphic.updateProps(progress, {
                            shape: {
                                endAngle: linearMap(val, valueExtent, angleExtent, isClip)
                            }
                        }, seriesModel);
                        group.add(progress);
                        // Add data index and series index for indexing the data by element
                        // Useful in tooltip
                        setCommonECData(seriesModel.seriesIndex, data.dataType, newIdx, progress);
                        progressList[newIdx] = progress;
                    }
                })
                .execute();

            data.each(function (idx) {
                const itemModel = data.getItemModel<GaugeDataItemOption>(idx);
                const emphasisModel = itemModel.getModel('emphasis');
                const focus = emphasisModel.get('focus');
                const blurScope = emphasisModel.get('blurScope');
                const emphasisDisabled = emphasisModel.get('disabled');
                if (showPointer) {
                    const pointer = data.getItemGraphicEl(idx) as ECSymbol;
                    const symbolStyle = data.getItemVisual(idx, 'style');
                    const visualColor = symbolStyle.fill;
                    if (pointer instanceof ZRImage) {
                        const pathStyle = pointer.style;
                        pointer.useStyle(extend({
                            image: pathStyle.image,
                            x: pathStyle.x, y: pathStyle.y,
                            width: pathStyle.width, height: pathStyle.height
                        }, symbolStyle));
                    }
                    else {
                        pointer.useStyle(symbolStyle);
                        pointer.type !== 'pointer' && pointer.setColor(visualColor);
                    }

                    pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle());


                    if (pointer.style.fill === 'auto') {
                        pointer.setStyle('fill', getColor(
                            linearMap(data.get(valueDim, idx) as number, valueExtent, [0, 1], true)
                        ));
                    }

                    (pointer as ECElement).z2EmphasisLift = 0;
                    setStatesStylesFromModel(pointer, itemModel);
                    toggleHoverEmphasis(pointer, focus, blurScope, emphasisDisabled);
                }

                if (showProgress) {
                    const progress = progressList[idx];
                    progress.useStyle(data.getItemVisual(idx, 'style'));
                    progress.setStyle(itemModel.getModel(['progress', 'itemStyle']).getItemStyle());
                    (progress as ECElement).z2EmphasisLift = 0;
                    setStatesStylesFromModel(progress, itemModel);
                    toggleHoverEmphasis(progress, focus, blurScope, emphasisDisabled);
                }
            });

            this._progressEls = progressList;
        }
    }

    _renderAnchor(
        seriesModel: GaugeSeriesModel,
        posInfo: PosInfo
    ) {
        const anchorModel = seriesModel.getModel('anchor');
        const showAnchor = anchorModel.get('show');
        if (showAnchor) {
            const anchorSize = anchorModel.get('size');
            const anchorType = anchorModel.get('icon');
            const offsetCenter = anchorModel.get('offsetCenter');
            const anchorKeepAspect = anchorModel.get('keepAspect');
            const anchor = createSymbol(
                anchorType,
                posInfo.cx - anchorSize / 2 + parsePercent(offsetCenter[0], posInfo.r),
                posInfo.cy - anchorSize / 2 + parsePercent(offsetCenter[1], posInfo.r),
                anchorSize,
                anchorSize,
                null,
                anchorKeepAspect
            ) as graphic.Path;
            anchor.z2 = anchorModel.get('showAbove') ? 1 : 0;
            anchor.setStyle(anchorModel.getModel('itemStyle').getItemStyle());
            this.group.add(anchor);
        }
    }

    _renderTitleAndDetail(
        seriesModel: GaugeSeriesModel,
        ecModel: GlobalModel,
        api: ExtensionAPI,
        getColor: (percent: number) => ColorString,
        posInfo: PosInfo
    ) {
        const data = seriesModel.getData();
        const valueDim = data.mapDimension('value');
        const minVal = +seriesModel.get('min');
        const maxVal = +seriesModel.get('max');

        const contentGroup = new graphic.Group();

        const newTitleEls: graphic.Text[] = [];
        const newDetailEls: graphic.Text[] = [];
        const hasAnimation = seriesModel.isAnimationEnabled();

        const showPointerAbove = seriesModel.get(['pointer', 'showAbove']);

        data.diff(this._data)
            .add((idx) => {
                newTitleEls[idx] = new graphic.Text({
                    silent: true
                });
                newDetailEls[idx] = new graphic.Text({
                    silent: true
                });
            })
            .update((idx, oldIdx) => {
                newTitleEls[idx] = this._titleEls[oldIdx];
                newDetailEls[idx] = this._detailEls[oldIdx];
            })
            .execute();

        data.each(function (idx) {
            const itemModel = data.getItemModel<GaugeDataItemOption>(idx);
            const value = data.get(valueDim, idx) as number;
            const itemGroup = new graphic.Group();
            const autoColor = getColor(
                linearMap(value, [minVal, maxVal], [0, 1], true)
            );

            const itemTitleModel = itemModel.getModel('title');
            if (itemTitleModel.get('show')) {
                const titleOffsetCenter = itemTitleModel.get('offsetCenter');
                const titleX = posInfo.cx + parsePercent(titleOffsetCenter[0], posInfo.r);
                const titleY = posInfo.cy + parsePercent(titleOffsetCenter[1], posInfo.r);
                const labelEl = newTitleEls[idx];
                labelEl.attr({
                    z2: showPointerAbove ? 0 : 2,
                    style: createTextStyle(itemTitleModel, {
                        x: titleX,
                        y: titleY,
                        text: data.getName(idx),
                        align: 'center',
                        verticalAlign: 'middle'
                    }, {inheritColor: autoColor})
                });

                itemGroup.add(labelEl);
            }

            const itemDetailModel = itemModel.getModel('detail');
            if (itemDetailModel.get('show')) {
                const detailOffsetCenter = itemDetailModel.get('offsetCenter');
                const detailX = posInfo.cx + parsePercent(detailOffsetCenter[0], posInfo.r);
                const detailY = posInfo.cy + parsePercent(detailOffsetCenter[1], posInfo.r);
                const width = parsePercent(itemDetailModel.get('width'), posInfo.r);
                const height = parsePercent(itemDetailModel.get('height'), posInfo.r);
                const detailColor = (
                    seriesModel.get(['progress', 'show']) ? data.getItemVisual(idx, 'style').fill : autoColor
                ) as string;
                const labelEl = newDetailEls[idx];
                const formatter = itemDetailModel.get('formatter');
                labelEl.attr({
                    z2: showPointerAbove ? 0 : 2,
                    style: createTextStyle(itemDetailModel, {
                        x: detailX,
                        y: detailY,
                        text: formatLabel(value, formatter),
                        width: isNaN(width) ? null : width,
                        height: isNaN(height) ? null : height,
                        align: 'center',
                        verticalAlign: 'middle'
                    }, {inheritColor: detailColor})
                });
                setLabelValueAnimation(
                    labelEl,
                    {normal: itemDetailModel},
                    value,
                    (value: number) => formatLabel(value, formatter)
                );
                hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel, {
                    getFormattedLabel(
                        labelDataIndex, status, dataType, labelDimIndex, fmt, extendParams
                    ) {
                        return formatLabel(
                            extendParams
                                ? extendParams.interpolatedValue as typeof value
                                : value,
                            formatter
                        );
                    }
                });

                itemGroup.add(labelEl);
            }

            contentGroup.add(itemGroup);
        });
        this.group.add(contentGroup);

        this._titleEls = newTitleEls;
        this._detailEls = newDetailEls;
    }

}

export default GaugeView;
