/*
* 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 {createTextStyle} from '../../label/labelStyle';
import Model from '../../model/Model';
import AxisView from './AxisView';
import AxisBuilder from './AxisBuilder';
import { AngleAxisModel } from '../../coord/polar/AxisModel';
import GlobalModel from '../../model/Global';
import Polar from '../../coord/polar/Polar';
import AngleAxis from '../../coord/polar/AngleAxis';
import { ZRTextAlign, ZRTextVerticalAlign, ColorString } from '../../util/types';
import { getECData } from '../../util/innerStore';

const elementList = [
    'axisLine',
    'axisLabel',
    'axisTick',
    'minorTick',
    'splitLine',
    'minorSplitLine',
    'splitArea'
] as const;

function getAxisLineShape(polar: Polar, rExtent: number[], angle: number) {
    rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse());
    const start = polar.coordToPoint([rExtent[0], angle]);
    const end = polar.coordToPoint([rExtent[1], angle]);

    return {
        x1: start[0],
        y1: start[1],
        x2: end[0],
        y2: end[1]
    };
}

function getRadiusIdx(polar: Polar) {
    const radiusAxis = polar.getRadiusAxis();
    return radiusAxis.inverse ? 0 : 1;
}

// Remove the last tick which will overlap the first tick
function fixAngleOverlap(list: TickCoord[]) {
    const firstItem = list[0];
    const lastItem = list[list.length - 1];
    if (firstItem
        && lastItem
        && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4
    ) {
        list.pop();
    }
}

type TickCoord = ReturnType<AngleAxis['getTicksCoords']>[number];
type TickLabel = ReturnType<AngleAxis['getViewLabels']>[number] & {
    coord: number
};

class AngleAxisView extends AxisView {

    static readonly type = 'angleAxis';
    readonly type = AngleAxisView.type;

    axisPointerClass = 'PolarAxisPointer';

    render(angleAxisModel: AngleAxisModel, ecModel: GlobalModel) {
        this.group.removeAll();
        if (!angleAxisModel.get('show')) {
            return;
        }

        const angleAxis = angleAxisModel.axis;
        const polar = angleAxis.polar;
        const radiusExtent = polar.getRadiusAxis().getExtent();

        const ticksAngles = angleAxis.getTicksCoords();
        const minorTickAngles = angleAxis.getMinorTicksCoords();

        const labels = zrUtil.map(angleAxis.getViewLabels(), function (labelItem: TickLabel) {
            labelItem = zrUtil.clone(labelItem);
            labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
            return labelItem;
        });

        fixAngleOverlap(labels);
        fixAngleOverlap(ticksAngles);

        zrUtil.each(elementList, function (name) {
            if (angleAxisModel.get([name, 'show'])
                && (!angleAxis.scale.isBlank() || name === 'axisLine')
            ) {
                angelAxisElementsBuilders[name](
                    this.group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels
                );
            }
        }, this);
    }

}

interface AngleAxisElementBuilder {
    (
        group: graphic.Group,
        angleAxisModel: AngleAxisModel,
        polar: Polar,
        ticksAngles: TickCoord[],
        minorTickAngles: TickCoord[][],
        radiusExtent: number[],
        labels?: TickLabel[]
    ): void
}

const angelAxisElementsBuilders: Record<typeof elementList[number], AngleAxisElementBuilder> = {

    axisLine(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
        const lineStyleModel = angleAxisModel.getModel(['axisLine', 'lineStyle']);

        // extent id of the axis radius (r0 and r)
        const rId = getRadiusIdx(polar);
        const r0Id = rId ? 0 : 1;

        let shape;
        if (radiusExtent[r0Id] === 0) {
            shape = new graphic.Circle({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: radiusExtent[rId]
                },
                style: lineStyleModel.getLineStyle(),
                z2: 1,
                silent: true
            });
        }
        else {
            shape = new graphic.Ring({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r: radiusExtent[rId],
                    r0: radiusExtent[r0Id]
                },
                style: lineStyleModel.getLineStyle(),
                z2: 1,
                silent: true
            });
        }
        shape.style.fill = null;
        group.add(shape);
    },

    axisTick(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
        const tickModel = angleAxisModel.getModel('axisTick');

        const tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
        const radius = radiusExtent[getRadiusIdx(polar)];

        const lines = zrUtil.map(ticksAngles, function (tickAngleItem) {
            return new graphic.Line({
                shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
            });
        });
        group.add(graphic.mergePath(
            lines, {
                style: zrUtil.defaults(
                    tickModel.getModel('lineStyle').getLineStyle(),
                    {
                        stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color'])
                    }
                )
            }
        ));
    },

    minorTick(group, angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) {
        if (!minorTickAngles.length) {
            return;
        }

        const tickModel = angleAxisModel.getModel('axisTick');
        const minorTickModel = angleAxisModel.getModel('minorTick');

        const tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length');
        const radius = radiusExtent[getRadiusIdx(polar)];

        const lines = [];

        for (let i = 0; i < minorTickAngles.length; i++) {
            for (let k = 0; k < minorTickAngles[i].length; k++) {
                lines.push(new graphic.Line({
                    shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord)
                }));
            }
        }

        group.add(graphic.mergePath(
            lines, {
                style: zrUtil.defaults(
                    minorTickModel.getModel('lineStyle').getLineStyle(),
                    zrUtil.defaults(
                        tickModel.getLineStyle(), {
                            stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color'])
                        }
                    )
                )
            }
        ));
    },

    axisLabel(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) {
        const rawCategoryData = angleAxisModel.getCategories(true);

        const commonLabelModel = angleAxisModel.getModel('axisLabel');

        const labelMargin = commonLabelModel.get('margin');
        const triggerEvent = angleAxisModel.get('triggerEvent');

        // Use length of ticksAngles because it may remove the last tick to avoid overlapping
        zrUtil.each(labels, function (labelItem, idx) {
            let labelModel = commonLabelModel;
            const tickValue = labelItem.tickValue;

            const r = radiusExtent[getRadiusIdx(polar)];
            const p = polar.coordToPoint([r + labelMargin, labelItem.coord]);
            const cx = polar.cx;
            const cy = polar.cy;

            const labelTextAlign: ZRTextAlign = Math.abs(p[0] - cx) / r < 0.3
                ? 'center' : (p[0] > cx ? 'left' : 'right');
            const labelTextVerticalAlign: ZRTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3
                ? 'middle' : (p[1] > cy ? 'top' : 'bottom');

            if (rawCategoryData && rawCategoryData[tickValue]) {
                const rawCategoryItem = rawCategoryData[tickValue];
                if (zrUtil.isObject(rawCategoryItem) && rawCategoryItem.textStyle) {
                    labelModel = new Model(
                        rawCategoryItem.textStyle, commonLabelModel, commonLabelModel.ecModel
                    );
                    }
            }

            const textEl = new graphic.Text({
                silent: AxisBuilder.isLabelSilent(angleAxisModel),
                style: createTextStyle(labelModel, {
                    x: p[0],
                    y: p[1],
                    fill: labelModel.getTextColor()
                        || angleAxisModel.get(['axisLine', 'lineStyle', 'color']) as ColorString,
                    text: labelItem.formattedLabel,
                    align: labelTextAlign,
                    verticalAlign: labelTextVerticalAlign
                })
            });
            group.add(textEl);

            // Pack data for mouse event
            if (triggerEvent) {
                const eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel);
                eventData.targetType = 'axisLabel';
                eventData.value = labelItem.rawLabel;
                getECData(textEl).eventData = eventData;
            }

        }, this);
    },

    splitLine(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
        const splitLineModel = angleAxisModel.getModel('splitLine');
        const lineStyleModel = splitLineModel.getModel('lineStyle');
        let lineColors = lineStyleModel.get('color');
        let lineCount = 0;

        lineColors = lineColors instanceof Array ? lineColors : [lineColors];

        const splitLines: graphic.Line[][] = [];

        for (let i = 0; i < ticksAngles.length; i++) {
            const colorIndex = (lineCount++) % lineColors.length;
            splitLines[colorIndex] = splitLines[colorIndex] || [];
            splitLines[colorIndex].push(new graphic.Line({
                shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
            }));
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (let i = 0; i < splitLines.length; i++) {
            group.add(graphic.mergePath(splitLines[i], {
                style: zrUtil.defaults({
                    stroke: lineColors[i % lineColors.length]
                }, lineStyleModel.getLineStyle()),
                silent: true,
                z: angleAxisModel.get('z')
            }));
        }
    },

    minorSplitLine(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
        if (!minorTickAngles.length) {
            return;
        }

        const minorSplitLineModel = angleAxisModel.getModel('minorSplitLine');
        const lineStyleModel = minorSplitLineModel.getModel('lineStyle');

        const lines = [];

        for (let i = 0; i < minorTickAngles.length; i++) {
            for (let k = 0; k < minorTickAngles[i].length; k++) {
                lines.push(new graphic.Line({
                    shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord)
                }));
            }
        }

        group.add(graphic.mergePath(lines, {
            style: lineStyleModel.getLineStyle(),
            silent: true,
            z: angleAxisModel.get('z')
        }));
    },

    splitArea(group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
        if (!ticksAngles.length) {
            return;
        }

        const splitAreaModel = angleAxisModel.getModel('splitArea');
        const areaStyleModel = splitAreaModel.getModel('areaStyle');
        let areaColors = areaStyleModel.get('color');
        let lineCount = 0;

        areaColors = areaColors instanceof Array ? areaColors : [areaColors];

        const splitAreas: graphic.Sector[][] = [];

        const RADIAN = Math.PI / 180;
        let prevAngle = -ticksAngles[0].coord * RADIAN;
        const r0 = Math.min(radiusExtent[0], radiusExtent[1]);
        const r1 = Math.max(radiusExtent[0], radiusExtent[1]);

        const clockwise = angleAxisModel.get('clockwise');

        for (let i = 1, len = ticksAngles.length; i <= len; i++) {
            const coord = i === len ? ticksAngles[0].coord : ticksAngles[i].coord;
            const colorIndex = (lineCount++) % areaColors.length;
            splitAreas[colorIndex] = splitAreas[colorIndex] || [];
            splitAreas[colorIndex].push(new graphic.Sector({
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r0: r0,
                    r: r1,
                    startAngle: prevAngle,
                    endAngle: -coord * RADIAN,
                    clockwise: clockwise
                },
                silent: true
            }));
            prevAngle = -coord * RADIAN;
        }

        // Simple optimization
        // Batching the lines if color are the same
        for (let i = 0; i < splitAreas.length; i++) {
            group.add(graphic.mergePath(splitAreas[i], {
                style: zrUtil.defaults({
                    fill: areaColors[i % areaColors.length]
                }, areaStyleModel.getAreaStyle()),
                silent: true
            }));
        }
    }
};

export default AngleAxisView;
