/*
* 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 { assert, isArray, eqNaN, isFunction } from 'zrender/src/core/util';
import Scale from '../scale/Scale';
import { AxisBaseModel } from './AxisBaseModel';
import { parsePercent } from 'zrender/src/contain/text';
import { AxisBaseOption } from './axisCommonTypes';
import { ScaleDataValue } from '../util/types';


export interface ScaleRawExtentResult {
    // `min`/`max` defines data available range, determined by
    // `dataMin`/`dataMax` and explicit specified min max related option.
    // The final extent will be based on the `min`/`max` and may be enlarge
    // a little (say, "nice strategy", e.g., niceScale, boundaryGap).
    // Ensure `min`/`max` be finite number or NaN here.
    // (not to be null/undefined) `NaN` means min/max axis is blank.
    readonly min: number;
    readonly max: number;
    // `minFixed`/`maxFixed` marks that `min`/`max` should be used
    // in the final extent without other "nice strategy".
    readonly minFixed: boolean;
    readonly maxFixed: boolean;
    // Mark that the axis should be blank.
    readonly isBlank: boolean;
}

export class ScaleRawExtentInfo {

    private _needCrossZero: boolean;
    private _isOrdinal: boolean;
    private _axisDataLen: number;
    private _boundaryGapInner: number[];

    // Accurate raw value get from model.
    private _modelMinRaw: AxisBaseOption['min'];
    private _modelMaxRaw: AxisBaseOption['max'];

    // Can be `finite number`/`null`/`undefined`/`NaN`
    private _modelMinNum: number;
    private _modelMaxNum: number;

    // Range union by series data on this axis.
    // May be modified if data is filtered.
    private _dataMin: number;
    private _dataMax: number;

    // Highest priority if specified.
    private _determinedMin: number;
    private _determinedMax: number;

    // Make that the `rawExtentInfo` can not be modified any more.
    readonly frozen: boolean;


    constructor(
        scale: Scale,
        model: AxisBaseModel,
        // Usually: data extent from all series on this axis.
        originalExtent: number[]
    ) {
        this._prepareParams(scale, model, originalExtent);
    }

    /**
     * Parameters depending on ouside (like model, user callback)
     * are prepared and fixed here.
     */
    private _prepareParams(
        scale: Scale,
        model: AxisBaseModel,
        // Usually: data extent from all series on this axis.
        dataExtent: number[]
    ) {
        if (dataExtent[1] < dataExtent[0]) {
            dataExtent = [NaN, NaN];
        }
        this._dataMin = dataExtent[0];
        this._dataMax = dataExtent[1];

        const isOrdinal = this._isOrdinal = scale.type === 'ordinal';
        this._needCrossZero = model.getNeedCrossZero && model.getNeedCrossZero();

        const modelMinRaw = this._modelMinRaw = model.get('min', true);
        if (isFunction(modelMinRaw)) {
            // This callback alway provide users the full data extent (before data filtered).
            this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({
                min: dataExtent[0],
                max: dataExtent[1]
            }));
        }
        else if (modelMinRaw !== 'dataMin') {
            this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw);
        }

        const modelMaxRaw = this._modelMaxRaw = model.get('max', true);
        if (isFunction(modelMaxRaw)) {
            // This callback alway provide users the full data extent (before data filtered).
            this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({
                min: dataExtent[0],
                max: dataExtent[1]
            }));
        }
        else if (modelMaxRaw !== 'dataMax') {
            this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw);
        }

        if (isOrdinal) {
            // FIXME: there is a flaw here: if there is no "block" data processor like `dataZoom`,
            // and progressive rendering is using, here the category result might just only contain
            // the processed chunk rather than the entire result.
            this._axisDataLen = model.getCategories().length;
        }
        else {
            const boundaryGap = model.get('boundaryGap');
            const boundaryGapArr = isArray(boundaryGap)
                ? boundaryGap : [boundaryGap || 0, boundaryGap || 0];

            if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') {
                if (__DEV__) {
                    console.warn('Boolean type for boundaryGap is only '
                        + 'allowed for ordinal axis. Please use string in '
                        + 'percentage instead, e.g., "20%". Currently, '
                        + 'boundaryGap is set to be 0.');
                }
                this._boundaryGapInner = [0, 0];
            }
            else {
                this._boundaryGapInner = [
                    parsePercent(boundaryGapArr[0], 1),
                    parsePercent(boundaryGapArr[1], 1)
                ];
            }
        }
    }

    /**
     * Calculate extent by prepared parameters.
     * This method has no external dependency and can be called duplicatedly,
     * getting the same result.
     * If parameters changed, should call this method to recalcuate.
     */
    calculate(): ScaleRawExtentResult {
        // Notice: When min/max is not set (that is, when there are null/undefined,
        // which is the most common case), these cases should be ensured:
        // (1) For 'ordinal', show all axis.data.
        // (2) For others:
        //      + `boundaryGap` is applied (if min/max set, boundaryGap is
        //      disabled).
        //      + If `needCrossZero`, min/max should be zero, otherwise, min/max should
        //      be the result that originalExtent enlarged by boundaryGap.
        // (3) If no data, it should be ensured that `scale.setBlank` is set.

        const isOrdinal = this._isOrdinal;
        const dataMin = this._dataMin;
        const dataMax = this._dataMax;
        const axisDataLen = this._axisDataLen;
        const boundaryGapInner = this._boundaryGapInner;

        const span = !isOrdinal
            ? ((dataMax - dataMin) || Math.abs(dataMin))
            : null;

        // Currently if a `'value'` axis model min is specified as 'dataMin'/'dataMax',
        // `boundaryGap` will not be used. It's the different from specifying as `null`/`undefined`.
        let min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum;
        let max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum;

        // If `_modelMinNum`/`_modelMaxNum` is `null`/`undefined`, should not be fixed.
        let minFixed = min != null;
        let maxFixed = max != null;

        if (min == null) {
            min = isOrdinal
                ? (axisDataLen ? 0 : NaN)
                : dataMin - boundaryGapInner[0] * span;
        }
        if (max == null) {
            max = isOrdinal
                ? (axisDataLen ? axisDataLen - 1 : NaN)
                : dataMax + boundaryGapInner[1] * span;
        }

        (min == null || !isFinite(min)) && (min = NaN);
        (max == null || !isFinite(max)) && (max = NaN);

        if (min > max) {
            min = NaN;
            max = NaN;
        }

        const isBlank = eqNaN(min)
            || eqNaN(max)
            || (isOrdinal && !axisDataLen);

        // If data extent modified, need to recalculated to ensure cross zero.
        if (this._needCrossZero) {
            // Axis is over zero and min is not set
            if (min > 0 && max > 0 && !minFixed) {
                min = 0;
                // minFixed = true;
            }
            // Axis is under zero and max is not set
            if (min < 0 && max < 0 && !maxFixed) {
                max = 0;
                // maxFixed = true;
            }
            // PENDING:
            // When `needCrossZero` and all data is positive/negative, should it be ensured
            // that the results processed by boundaryGap are positive/negative?
            // If so, here `minFixed`/`maxFixed` need to be set.
        }

        const determinedMin = this._determinedMin;
        const determinedMax = this._determinedMax;
        if (determinedMin != null) {
            min = determinedMin;
            minFixed = true;
        }
        if (determinedMax != null) {
            max = determinedMax;
            maxFixed = true;
        }

        // Ensure min/max be finite number or NaN here. (not to be null/undefined)
        // `NaN` means min/max axis is blank.
        return {
            min: min,
            max: max,
            minFixed: minFixed,
            maxFixed: maxFixed,
            isBlank: isBlank
        };
    }

    modifyDataMinMax(minMaxName: 'min' | 'max', val: number): void {
        if (__DEV__) {
            assert(!this.frozen);
        }
        this[DATA_MIN_MAX_ATTR[minMaxName]] = val;
    }

    setDeterminedMinMax(minMaxName: 'min' | 'max', val: number): void {
        const attr = DETERMINED_MIN_MAX_ATTR[minMaxName];
        if (__DEV__) {
            assert(
                !this.frozen
                // Earse them usually means logic flaw.
                && (this[attr] == null)
            );
        }
        this[attr] = val;
    }

    freeze() {
        // @ts-ignore
        this.frozen = true;
    }
}

const DETERMINED_MIN_MAX_ATTR = { min: '_determinedMin', max: '_determinedMax' } as const;
const DATA_MIN_MAX_ATTR = { min: '_dataMin', max: '_dataMax' } as const;

/**
 * Get scale min max and related info only depends on model settings.
 * This method can be called after coordinate system created.
 * For example, in data processing stage.
 *
 * Scale extent info probably be required multiple times during a workflow.
 * For example:
 * (1) `dataZoom` depends it to get the axis extent in "100%" state.
 * (2) `processor/extentCalculator` depends it to make sure whether axis extent is specified.
 * (3) `coordSys.update` use it to finally decide the scale extent.
 * But the callback of `min`/`max` should not be called multiple times.
 * The code below should not be implemented repeatedly either.
 * So we cache the result in the scale instance, which will be recreated at the begining
 * of the workflow (because `scale` instance will be recreated each round of the workflow).
 */
export function ensureScaleRawExtentInfo(
    scale: Scale,
    model: AxisBaseModel,
    // Usually: data extent from all series on this axis.
    originalExtent: number[]
): ScaleRawExtentInfo {

    // Do not permit to recreate.
    let rawExtentInfo = scale.rawExtentInfo;
    if (rawExtentInfo) {
        return rawExtentInfo;
    }

    rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent);
    // @ts-ignore
    scale.rawExtentInfo = rawExtentInfo;

    return rawExtentInfo;
}

export function parseAxisModelMinMax(scale: Scale, minMax: ScaleDataValue): number {
    return minMax == null ? null
        : eqNaN(minMax) ? NaN
        : scale.parse(minMax);
}
