/*
* 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 {each, map} from 'zrender/src/core/util';
import {linearMap, getPixelPrecision, round} from '../util/number';
import {
    createAxisTicks,
    createAxisLabels,
    calculateCategoryInterval
} from './axisTickLabelBuilder';
import Scale from '../scale/Scale';
import { DimensionName, ScaleDataValue, ScaleTick } from '../util/types';
import OrdinalScale from '../scale/Ordinal';
import Model from '../model/Model';
import { AxisBaseOption, CategoryAxisBaseOption, OptionAxisType } from './axisCommonTypes';
import { AxisBaseModel } from './AxisBaseModel';

const NORMALIZED_EXTENT = [0, 1] as [number, number];

interface TickCoord {
    coord: number;
    // That is `scaleTick.value`.
    tickValue?: ScaleTick['value'];
}

/**
 * Base class of Axis.
 */
class Axis {

    /**
     * Axis type
     *  - 'category'
     *  - 'value'
     *  - 'time'
     *  - 'log'
     */
    type: OptionAxisType;

    // Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'.
    readonly dim: DimensionName;

    // Axis scale
    scale: Scale;

    private _extent: [number, number];

    // Injected outside
    model: AxisBaseModel;
    onBand: CategoryAxisBaseOption['boundaryGap'] = false;
    inverse: AxisBaseOption['inverse'] = false;


    constructor(dim: DimensionName, scale: Scale, extent: [number, number]) {
        this.dim = dim;
        this.scale = scale;
        this._extent = extent || [0, 0];
    }

    /**
     * If axis extent contain given coord
     */
    contain(coord: number): boolean {
        const extent = this._extent;
        const min = Math.min(extent[0], extent[1]);
        const max = Math.max(extent[0], extent[1]);
        return coord >= min && coord <= max;
    }

    /**
     * If axis extent contain given data
     */
    containData(data: ScaleDataValue): boolean {
        return this.scale.contain(data);
    }

    /**
     * Get coord extent.
     */
    getExtent(): [number, number] {
        return this._extent.slice() as [number, number];
    }

    /**
     * Get precision used for formatting
     */
    getPixelPrecision(dataExtent?: [number, number]): number {
        return getPixelPrecision(
            dataExtent || this.scale.getExtent(),
            this._extent
        );
    }

    /**
     * Set coord extent
     */
    setExtent(start: number, end: number): void {
        const extent = this._extent;
        extent[0] = start;
        extent[1] = end;
    }

    /**
     * Convert data to coord. Data is the rank if it has an ordinal scale
     */
    dataToCoord(data: ScaleDataValue, clamp?: boolean): number {
        let extent = this._extent;
        const scale = this.scale;
        data = scale.normalize(data);

        if (this.onBand && scale.type === 'ordinal') {
            extent = extent.slice() as [number, number];
            fixExtentWithBands(extent, (scale as OrdinalScale).count());
        }

        return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
    }

    /**
     * Convert coord to data. Data is the rank if it has an ordinal scale
     */
    coordToData(coord: number, clamp?: boolean): number {
        let extent = this._extent;
        const scale = this.scale;

        if (this.onBand && scale.type === 'ordinal') {
            extent = extent.slice() as [number, number];
            fixExtentWithBands(extent, (scale as OrdinalScale).count());
        }

        const t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);

        return this.scale.scale(t);
    }

    /**
     * Convert pixel point to data in axis
     */
    pointToData(point: number[], clamp?: boolean): number {
        // Should be implemented in derived class if necessary.
        return;
    }

    /**
     * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,
     * `axis.getTicksCoords` considers `onBand`, which is used by
     * `boundaryGap:true` of category axis and splitLine and splitArea.
     * @param opt.tickModel default: axis.model.getModel('axisTick')
     * @param opt.clamp If `true`, the first and the last
     *        tick must be at the axis end points. Otherwise, clip ticks
     *        that outside the axis extent.
     */
    getTicksCoords(opt?: {
        tickModel?: Model,
        clamp?: boolean
    }): TickCoord[] {
        opt = opt || {};

        const tickModel = opt.tickModel || this.getTickModel();
        const result = createAxisTicks(this, tickModel as AxisBaseModel);
        const ticks = result.ticks;

        const ticksCoords = map(ticks, function (tickVal) {
            return {
                coord: this.dataToCoord(
                    this.scale.type === 'ordinal'
                        ? (this.scale as OrdinalScale).getRawOrdinalNumber(tickVal)
                        : tickVal
                ),
                tickValue: tickVal
            };
        }, this);

        const alignWithLabel = tickModel.get('alignWithLabel');

        fixOnBandTicksCoords(
            this, ticksCoords, alignWithLabel, opt.clamp
        );

        return ticksCoords;
    }

    getMinorTicksCoords(): TickCoord[][] {
        if (this.scale.type === 'ordinal') {
            // Category axis doesn't support minor ticks
            return [];
        }

        const minorTickModel = this.model.getModel('minorTick');
        let splitNumber = minorTickModel.get('splitNumber');
        // Protection.
        if (!(splitNumber > 0 && splitNumber < 100)) {
            splitNumber = 5;
        }
        const minorTicks = this.scale.getMinorTicks(splitNumber);
        const minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
            return map(minorTicksGroup, function (minorTick) {
                return {
                    coord: this.dataToCoord(minorTick),
                    tickValue: minorTick
                };
            }, this);
        }, this);
        return minorTicksCoords;
    }

    getViewLabels(): ReturnType<typeof createAxisLabels>['labels'] {
        return createAxisLabels(this).labels;
    }

    getLabelModel(): Model<AxisBaseOption['axisLabel']> {
        return this.model.getModel('axisLabel');
    }

    /**
     * Notice here we only get the default tick model. For splitLine
     * or splitArea, we should pass the splitLineModel or splitAreaModel
     * manually when calling `getTicksCoords`.
     * In GL, this method may be overridden to:
     * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));`
     */
    getTickModel(): Model {
        return this.model.getModel('axisTick');
    }

    /**
     * Get width of band
     */
    getBandWidth(): number {
        const axisExtent = this._extent;
        const dataExtent = this.scale.getExtent();

        let len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0);
        // Fix #2728, avoid NaN when only one data.
        len === 0 && (len = 1);

        const size = Math.abs(axisExtent[1] - axisExtent[0]);

        return Math.abs(size) / len;
    }

    /**
     * Get axis rotate, by degree.
     */
    getRotate: () => number;

    /**
     * Only be called in category axis.
     * Can be overridden, consider other axes like in 3D.
     * @return Auto interval for cateogry axis tick and label
     */
    calculateCategoryInterval(): ReturnType<typeof calculateCategoryInterval> {
        return calculateCategoryInterval(this);
    }

}

function fixExtentWithBands(extent: [number, number], nTick: number): void {
    const size = extent[1] - extent[0];
    const len = nTick;
    const margin = size / len / 2;
    extent[0] += margin;
    extent[1] -= margin;
}

// If axis has labels [1, 2, 3, 4]. Bands on the axis are
// |---1---|---2---|---3---|---4---|.
// So the displayed ticks and splitLine/splitArea should between
// each data item, otherwise cause misleading (e.g., split tow bars
// of a single data item when there are two bar series).
// Also consider if tickCategoryInterval > 0 and onBand, ticks and
// splitLine/spliteArea should layout appropriately corresponding
// to displayed labels. (So we should not use `getBandWidth` in this
// case).
function fixOnBandTicksCoords(
    axis: Axis, ticksCoords: TickCoord[], alignWithLabel: boolean, clamp: boolean
) {
    const ticksLen = ticksCoords.length;

    if (!axis.onBand || alignWithLabel || !ticksLen) {
        return;
    }

    const axisExtent = axis.getExtent();
    let last;
    let diffSize;
    if (ticksLen === 1) {
        ticksCoords[0].coord = axisExtent[0];
        last = ticksCoords[1] = {coord: axisExtent[0]};
    }
    else {
        const crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
        const shift = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;

        each(ticksCoords, function (ticksItem) {
            ticksItem.coord -= shift / 2;
        });

        const dataExtent = axis.scale.getExtent();
        diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;

        last = {coord: ticksCoords[ticksLen - 1].coord + shift * diffSize};

        ticksCoords.push(last);
    }

    const inverse = axisExtent[0] > axisExtent[1];

    // Handling clamp.
    if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
        clamp ? (ticksCoords[0].coord = axisExtent[0]) : ticksCoords.shift();
    }
    if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) {
        ticksCoords.unshift({coord: axisExtent[0]});
    }
    if (littleThan(axisExtent[1], last.coord)) {
        clamp ? (last.coord = axisExtent[1]) : ticksCoords.pop();
    }
    if (clamp && littleThan(last.coord, axisExtent[1])) {
        ticksCoords.push({coord: axisExtent[1]});
    }

    function littleThan(a: number, b: number): boolean {
        // Avoid rounding error cause calculated tick coord different with extent.
        // It may cause an extra unnecessary tick added.
        a = round(a);
        b = round(b);
        return inverse ? a > b : a < b;
    }
}

export default Axis;
