/*
* 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.
*/

/**
 * Grid is a region which contains at most 4 cartesian systems
 *
 * TODO Default cartesian
 */

import {isObject, each, indexOf, retrieve3, keys} from 'zrender/src/core/util';
import {getLayoutRect, LayoutRect} from '../../util/layout';
import {
    createScaleByModel,
    ifAxisCrossZero,
    niceScaleExtent,
    estimateLabelUnionRect,
    getDataDimensionsOnAxis
} from '../../coord/axisHelper';
import Cartesian2D, {cartesian2DDimensions} from './Cartesian2D';
import Axis2D from './Axis2D';
import {ParsedModelFinder, ParsedModelFinderKnown, SINGLE_REFERRING} from '../../util/model';

// Depends on GridModel, AxisModel, which performs preprocess.
import GridModel from './GridModel';
import CartesianAxisModel from './AxisModel';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { Dictionary } from 'zrender/src/core/types';
import {CoordinateSystemMaster} from '../CoordinateSystem';
import { ScaleDataValue } from '../../util/types';
import SeriesData from '../../data/SeriesData';
import OrdinalScale from '../../scale/Ordinal';
import { isCartesian2DSeries, findAxisModels } from './cartesianAxisHelper';
import { CategoryAxisBaseOption, NumericAxisBaseOptionCommon } from '../axisCommonTypes';
import { AxisBaseModel } from '../AxisBaseModel';
import { isIntervalOrLogScale } from '../../scale/helper';
import { alignScaleTicks } from '../axisAlignTicks';
import IntervalScale from '../../scale/Interval';
import LogScale from '../../scale/Log';


type Cartesian2DDimensionName = 'x' | 'y';

type FinderAxisIndex = {xAxisIndex?: number, yAxisIndex?: number};
type AxesMap = {
    x: Axis2D[],
    y: Axis2D[]
};

class Grid implements CoordinateSystemMaster {

    // FIXME:TS where used (different from registered type 'cartesian2d')?
    readonly type: string = 'grid';

    private _coordsMap: Dictionary<Cartesian2D> = {};
    private _coordsList: Cartesian2D[] = [];
    private _axesMap: AxesMap = {} as AxesMap;
    private _axesList: Axis2D[] = [];
    private _rect: LayoutRect;

    readonly model: GridModel;
    readonly axisPointerEnabled = true;

    // Injected:
    name: string;

    // For deciding which dimensions to use when creating list data
    static dimensions = cartesian2DDimensions;
    readonly dimensions = cartesian2DDimensions;

    constructor(gridModel: GridModel, ecModel: GlobalModel, api: ExtensionAPI) {
        this._initCartesian(gridModel, ecModel, api);
        this.model = gridModel;
    }

    getRect(): LayoutRect {
        return this._rect;
    }

    update(ecModel: GlobalModel, api: ExtensionAPI): void {

        const axesMap = this._axesMap;

        this._updateScale(ecModel, this.model);

        function updateAxisTicks(axes: Record<number, Axis2D>) {
            let alignTo: Axis2D;
            // Axis is added in order of axisIndex.
            const axesIndices = keys(axes);
            const len = axesIndices.length;
            if (!len) {
                return;
            }
            const axisNeedsAlign: Axis2D[] = [];
            // Process once and calculate the ticks for those don't use alignTicks.
            for (let i = len - 1; i >= 0; i--) {
                const idx = +axesIndices[i];    // Convert to number.
                const axis = axes[idx];
                const model = axis.model as AxisBaseModel<NumericAxisBaseOptionCommon>;
                const scale = axis.scale;
                if (// Only value and log axis without interval support alignTicks.
                    isIntervalOrLogScale(scale)
                    && model.get('alignTicks')
                    && model.get('interval') == null
                ) {
                    axisNeedsAlign.push(axis);
                }
                else {
                    niceScaleExtent(scale, model);
                    if (isIntervalOrLogScale(scale)) {  // Can only align to interval or log axis.
                        alignTo = axis;
                    }
                }
            };
            // All axes has set alignTicks. Pick the first one.
            // PENDING. Should we find the axis that both set interval, min, max and align to this one?
            if (axisNeedsAlign.length) {
                if (!alignTo) {
                    alignTo = axisNeedsAlign.pop();
                    niceScaleExtent(alignTo.scale, alignTo.model);
                }

                each(axisNeedsAlign, axis => {
                    alignScaleTicks(
                        axis.scale as IntervalScale | LogScale,
                        axis.model,
                        alignTo.scale as IntervalScale | LogScale
                    );
                });
            }
        }

        updateAxisTicks(axesMap.x);
        updateAxisTicks(axesMap.y);

        // Key: axisDim_axisIndex, value: boolean, whether onZero target.
        const onZeroRecords = {} as Dictionary<boolean>;

        each(axesMap.x, function (xAxis) {
            fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords);
        });
        each(axesMap.y, function (yAxis) {
            fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords);
        });

        // Resize again if containLabel is enabled
        // FIXME It may cause getting wrong grid size in data processing stage
        this.resize(this.model, api);
    }

    /**
     * Resize the grid
     */
    resize(gridModel: GridModel, api: ExtensionAPI, ignoreContainLabel?: boolean): void {

        const boxLayoutParams = gridModel.getBoxLayoutParams();
        const isContainLabel = !ignoreContainLabel && gridModel.get('containLabel');

        const gridRect = getLayoutRect(
            boxLayoutParams, {
                width: api.getWidth(),
                height: api.getHeight()
            });

        this._rect = gridRect;

        const axesList = this._axesList;

        adjustAxes();

        // Minus label size
        if (isContainLabel) {
            each(axesList, function (axis) {
                if (!axis.model.get(['axisLabel', 'inside'])) {
                    const labelUnionRect = estimateLabelUnionRect(axis);
                    if (labelUnionRect) {
                        const dim: 'height' | 'width' = axis.isHorizontal() ? 'height' : 'width';
                        const margin = axis.model.get(['axisLabel', 'margin']);
                        gridRect[dim] -= labelUnionRect[dim] + margin;
                        if (axis.position === 'top') {
                            gridRect.y += labelUnionRect.height + margin;
                        }
                        else if (axis.position === 'left') {
                            gridRect.x += labelUnionRect.width + margin;
                        }
                    }
                }
            });

            adjustAxes();
        }

        each(this._coordsList, function (coord) {
            // Calculate affine matrix to accelerate the data to point transform.
            // If all the axes scales are time or value.
            coord.calcAffineTransform();
        });

        function adjustAxes() {
            each(axesList, function (axis) {
                const isHorizontal = axis.isHorizontal();
                const extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height];
                const idx = axis.inverse ? 1 : 0;
                axis.setExtent(extent[idx], extent[1 - idx]);
                updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y);
            });
        }
    }

    getAxis(dim: Cartesian2DDimensionName, axisIndex?: number): Axis2D {
        const axesMapOnDim = this._axesMap[dim];
        if (axesMapOnDim != null) {
            return axesMapOnDim[axisIndex || 0];
        }
    }

    getAxes(): Axis2D[] {
        return this._axesList.slice();
    }

    /**
     * Usage:
     *      grid.getCartesian(xAxisIndex, yAxisIndex);
     *      grid.getCartesian(xAxisIndex);
     *      grid.getCartesian(null, yAxisIndex);
     *      grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...});
     *
     * When only xAxisIndex or yAxisIndex given, find its first cartesian.
     */
    getCartesian(finder: FinderAxisIndex): Cartesian2D;
    getCartesian(xAxisIndex?: number, yAxisIndex?: number): Cartesian2D;
    getCartesian(xAxisIndex?: number | FinderAxisIndex, yAxisIndex?: number) {
        if (xAxisIndex != null && yAxisIndex != null) {
            const key = 'x' + xAxisIndex + 'y' + yAxisIndex;
            return this._coordsMap[key];
        }

        if (isObject(xAxisIndex)) {
            yAxisIndex = (xAxisIndex as FinderAxisIndex).yAxisIndex;
            xAxisIndex = (xAxisIndex as FinderAxisIndex).xAxisIndex;
        }
        for (let i = 0, coordList = this._coordsList; i < coordList.length; i++) {
            if (coordList[i].getAxis('x').index === xAxisIndex
                || coordList[i].getAxis('y').index === yAxisIndex
            ) {
                return coordList[i];
            }
        }
    }

    getCartesians(): Cartesian2D[] {
        return this._coordsList.slice();
    }

    /**
     * @implements
     */
    convertToPixel(
        ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue | ScaleDataValue[]
    ): number | number[] {
        const target = this._findConvertTarget(finder);

        return target.cartesian
            ? target.cartesian.dataToPoint(value as ScaleDataValue[])
            : target.axis
            ? target.axis.toGlobalCoord(target.axis.dataToCoord(value as ScaleDataValue))
            : null;
    }

    /**
     * @implements
     */
    convertFromPixel(
        ecModel: GlobalModel, finder: ParsedModelFinder, value: number | number[]
    ): number | number[] {
        const target = this._findConvertTarget(finder);

        return target.cartesian
            ? target.cartesian.pointToData(value as number[])
            : target.axis
            ? target.axis.coordToData(target.axis.toLocalCoord(value as number))
            : null;
    }

    private _findConvertTarget(finder: ParsedModelFinderKnown): {
        cartesian: Cartesian2D,
        axis: Axis2D
    } {
        const seriesModel = finder.seriesModel;
        const xAxisModel = finder.xAxisModel
            || (seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]);
        const yAxisModel = finder.yAxisModel
            || (seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]);
        const gridModel = finder.gridModel;
        const coordsList = this._coordsList;
        let cartesian: Cartesian2D;
        let axis;

        if (seriesModel) {
            cartesian = seriesModel.coordinateSystem as Cartesian2D;
            indexOf(coordsList, cartesian) < 0 && (cartesian = null);
        }
        else if (xAxisModel && yAxisModel) {
            cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
        }
        else if (xAxisModel) {
            axis = this.getAxis('x', xAxisModel.componentIndex);
        }
        else if (yAxisModel) {
            axis = this.getAxis('y', yAxisModel.componentIndex);
        }
        // Lowest priority.
        else if (gridModel) {
            const grid = gridModel.coordinateSystem;
            if (grid === this) {
                cartesian = this._coordsList[0];
            }
        }

        return {cartesian: cartesian, axis: axis};
    }

    /**
     * @implements
     */
    containPoint(point: number[]): boolean {
        const coord = this._coordsList[0];
        if (coord) {
            return coord.containPoint(point);
        }
    }

    /**
     * Initialize cartesian coordinate systems
     */
    private _initCartesian(
        gridModel: GridModel, ecModel: GlobalModel, api: ExtensionAPI
    ): void {
        const grid = this;
        const axisPositionUsed = {
            left: false,
            right: false,
            top: false,
            bottom: false
        };

        const axesMap = {
            x: {},
            y: {}
        } as AxesMap;
        const axesCount = {
            x: 0,
            y: 0
        };

        // Create axis
        ecModel.eachComponent('xAxis', createAxisCreator('x'), this);
        ecModel.eachComponent('yAxis', createAxisCreator('y'), this);

        if (!axesCount.x || !axesCount.y) {
            // Roll back when there no either x or y axis
            this._axesMap = {} as AxesMap;
            this._axesList = [];
            return;
        }

        this._axesMap = axesMap;

        // Create cartesian2d
        each(axesMap.x, (xAxis, xAxisIndex) => {
            each(axesMap.y, (yAxis, yAxisIndex) => {
                const key = 'x' + xAxisIndex + 'y' + yAxisIndex;
                const cartesian = new Cartesian2D(key);

                cartesian.master = this;
                cartesian.model = gridModel;

                this._coordsMap[key] = cartesian;
                this._coordsList.push(cartesian);

                cartesian.addAxis(xAxis);
                cartesian.addAxis(yAxis);
            });
        });

        function createAxisCreator(dimName: Cartesian2DDimensionName) {
            return function (axisModel: CartesianAxisModel, idx: number): void {
                if (!isAxisUsedInTheGrid(axisModel, gridModel)) {
                    return;
                }

                let axisPosition = axisModel.get('position');
                if (dimName === 'x') {
                    // Fix position
                    if (axisPosition !== 'top' && axisPosition !== 'bottom') {
                        // Default bottom of X
                        axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom';
                    }
                }
                else {
                    // Fix position
                    if (axisPosition !== 'left' && axisPosition !== 'right') {
                        // Default left of Y
                        axisPosition = axisPositionUsed.left ? 'right' : 'left';
                    }
                }
                axisPositionUsed[axisPosition] = true;

                const axis = new Axis2D(
                    dimName,
                    createScaleByModel(axisModel),
                    [0, 0],
                    axisModel.get('type'),
                    axisPosition
                );

                const isCategory = axis.type === 'category';
                axis.onBand = isCategory && (axisModel as AxisBaseModel<CategoryAxisBaseOption>).get('boundaryGap');
                axis.inverse = axisModel.get('inverse');

                // Inject axis into axisModel
                axisModel.axis = axis;

                // Inject axisModel into axis
                axis.model = axisModel;

                // Inject grid info axis
                axis.grid = grid;

                // Index of axis, can be used as key
                axis.index = idx;

                grid._axesList.push(axis);

                axesMap[dimName][idx] = axis;
                axesCount[dimName]++;
            };
        }
    }

    /**
     * Update cartesian properties from series.
     */
    private _updateScale(ecModel: GlobalModel, gridModel: GridModel): void {
        // Reset scale
        each(this._axesList, function (axis) {
            axis.scale.setExtent(Infinity, -Infinity);
            if (axis.type === 'category') {
                const categorySortInfo = axis.model.get('categorySortInfo');
                (axis.scale as OrdinalScale).setSortInfo(categorySortInfo);
            }
        });

        ecModel.eachSeries(function (seriesModel) {
            if (isCartesian2DSeries(seriesModel)) {
                const axesModelMap = findAxisModels(seriesModel);
                const xAxisModel = axesModelMap.xAxisModel;
                const yAxisModel = axesModelMap.yAxisModel;

                if (!isAxisUsedInTheGrid(xAxisModel, gridModel)
                    || !isAxisUsedInTheGrid(yAxisModel, gridModel)
                ) {
                    return;
                }

                const cartesian = this.getCartesian(
                    xAxisModel.componentIndex, yAxisModel.componentIndex
                );
                const data = seriesModel.getData();
                const xAxis = cartesian.getAxis('x');
                const yAxis = cartesian.getAxis('y');

                unionExtent(data, xAxis);
                unionExtent(data, yAxis);
            }
        }, this);

        function unionExtent(data: SeriesData, axis: Axis2D): void {
            each(getDataDimensionsOnAxis(data, axis.dim), function (dim) {
                axis.scale.unionExtentFromData(data, dim);
            });
        }
    }

    /**
     * @param dim 'x' or 'y' or 'auto' or null/undefined
     */
    getTooltipAxes(dim: Cartesian2DDimensionName | 'auto'): {
        baseAxes: Axis2D[], otherAxes: Axis2D[]
    } {
        const baseAxes = [] as Axis2D[];
        const otherAxes = [] as Axis2D[];

        each(this.getCartesians(), function (cartesian) {
            const baseAxis = (dim != null && dim !== 'auto')
                ? cartesian.getAxis(dim) : cartesian.getBaseAxis();
            const otherAxis = cartesian.getOtherAxis(baseAxis);
            indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
            indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
        });

        return {baseAxes: baseAxes, otherAxes: otherAxes};
    }


    static create(ecModel: GlobalModel, api: ExtensionAPI): Grid[] {
        const grids = [] as Grid[];
        ecModel.eachComponent('grid', function (gridModel: GridModel, idx) {
            const grid = new Grid(gridModel, ecModel, api);
            grid.name = 'grid_' + idx;
            // dataSampling requires axis extent, so resize
            // should be performed in create stage.
            grid.resize(gridModel, api, true);

            gridModel.coordinateSystem = grid;

            grids.push(grid);
        });

        // Inject the coordinateSystems into seriesModel
        ecModel.eachSeries(function (seriesModel) {
            if (!isCartesian2DSeries(seriesModel)) {
                return;
            }

            const axesModelMap = findAxisModels(seriesModel);
            const xAxisModel = axesModelMap.xAxisModel;
            const yAxisModel = axesModelMap.yAxisModel;

            const gridModel = xAxisModel.getCoordSysModel();

            if (__DEV__) {
                if (!gridModel) {
                    throw new Error(
                        'Grid "' + retrieve3(
                            xAxisModel.get('gridIndex'),
                            xAxisModel.get('gridId'),
                            0
                        ) + '" not found'
                    );
                }
                if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) {
                    throw new Error('xAxis and yAxis must use the same grid');
                }
            }

            const grid = gridModel.coordinateSystem as Grid;

            seriesModel.coordinateSystem = grid.getCartesian(
                xAxisModel.componentIndex, yAxisModel.componentIndex
            );
        });

        return grids;
    }

}

/**
 * Check if the axis is used in the specified grid.
 */
function isAxisUsedInTheGrid(axisModel: CartesianAxisModel, gridModel: GridModel): boolean {
    return axisModel.getCoordSysModel() === gridModel;
}

function fixAxisOnZero(
    axesMap: AxesMap,
    otherAxisDim: Cartesian2DDimensionName,
    axis: Axis2D,
    // Key: see `getOnZeroRecordKey`
    onZeroRecords: Dictionary<boolean>
): void {

    axis.getAxesOnZeroOf = function () {
        // TODO: onZero of multiple axes.
        return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : [];
    };

    // onZero can not be enabled in these two situations:
    // 1. When any other axis is a category axis.
    // 2. When no axis is cross 0 point.
    const otherAxes = axesMap[otherAxisDim];

    let otherAxisOnZeroOf: Axis2D;
    const axisModel = axis.model;
    const onZero = axisModel.get(['axisLine', 'onZero']);
    const onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']);

    if (!onZero) {
        return;
    }

    // If target axis is specified.
    if (onZeroAxisIndex != null) {
        if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) {
            otherAxisOnZeroOf = otherAxes[onZeroAxisIndex];
        }
    }
    else {
        // Find the first available other axis.
        for (const idx in otherAxes) {
            if (otherAxes.hasOwnProperty(idx)
                && canOnZeroToAxis(otherAxes[idx])
                // Consider that two Y axes on one value axis,
                // if both onZero, the two Y axes overlap.
                && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]
            ) {
                otherAxisOnZeroOf = otherAxes[idx];
                break;
            }
        }
    }

    if (otherAxisOnZeroOf) {
        onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true;
    }

    function getOnZeroRecordKey(axis: Axis2D) {
        return axis.dim + '_' + axis.index;
    }
}

function canOnZeroToAxis(axis: Axis2D): boolean {
    return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis);
}

function updateAxisTransform(axis: Axis2D, coordBase: number) {
    const axisExtent = axis.getExtent();
    const axisExtentSum = axisExtent[0] + axisExtent[1];

    // Fast transform
    axis.toGlobalCoord = axis.dim === 'x'
        ? function (coord) {
            return coord + coordBase;
        }
        : function (coord) {
            return axisExtentSum - coord + coordBase;
        };
    axis.toLocalCoord = axis.dim === 'x'
        ? function (coord) {
            return coord - coordBase;
        }
        : function (coord) {
            return axisExtentSum - coord + coordBase;
        };
}

export default Grid;
