/*
* 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 BoundingRect from 'zrender/src/core/BoundingRect';
import Cartesian from './Cartesian';
import { ScaleDataValue } from '../../util/types';
import Axis2D from './Axis2D';
import { CoordinateSystem } from '../CoordinateSystem';
import GridModel from './GridModel';
import Grid from './Grid';
import Scale from '../../scale/Scale';
import { invert } from 'zrender/src/core/matrix';
import { applyTransform } from 'zrender/src/core/vector';

export const cartesian2DDimensions = ['x', 'y'];

function canCalculateAffineTransform(scale: Scale) {
    return scale.type === 'interval' || scale.type === 'time';
}

class Cartesian2D extends Cartesian<Axis2D> implements CoordinateSystem {

    readonly type = 'cartesian2d';

    readonly dimensions = cartesian2DDimensions;

    model: GridModel;

    master: Grid;

    private _transform: number[];
    private _invTransform: number[];

    /**
     * Calculate an affine transform matrix if two axes are time or value.
     * It's mainly for accelartion on the large time series data.
     */
    calcAffineTransform() {
        this._transform = this._invTransform = null;

        const xAxisScale = this.getAxis('x').scale;
        const yAxisScale = this.getAxis('y').scale;

        if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) {
            return;
        }

        const xScaleExtent = xAxisScale.getExtent();
        const yScaleExtent = yAxisScale.getExtent();

        const start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]);
        const end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]);

        const xScaleSpan = xScaleExtent[1] - xScaleExtent[0];
        const yScaleSpan = yScaleExtent[1] - yScaleExtent[0];

        if (!xScaleSpan || !yScaleSpan) {
            return;
        }
        // Accelerate data to point calculation on the special large time series data.
        const scaleX = (end[0] - start[0]) / xScaleSpan;
        const scaleY = (end[1] - start[1]) / yScaleSpan;
        const translateX = start[0] - xScaleExtent[0] * scaleX;
        const translateY = start[1] - yScaleExtent[0] * scaleY;

        const m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY];
        this._invTransform = invert([], m);
    }

    /**
     * Base axis will be used on stacking.
     */
    getBaseAxis(): Axis2D {
        return this.getAxesByScale('ordinal')[0]
            || this.getAxesByScale('time')[0]
            || this.getAxis('x');
    }

    containPoint(point: number[]): boolean {
        const axisX = this.getAxis('x');
        const axisY = this.getAxis('y');
        return axisX.contain(axisX.toLocalCoord(point[0]))
            && axisY.contain(axisY.toLocalCoord(point[1]));
    }

    containData(data: ScaleDataValue[]): boolean {
        return this.getAxis('x').containData(data[0])
            && this.getAxis('y').containData(data[1]);
    }

    containZone(data1: ScaleDataValue[], data2: ScaleDataValue[]): boolean {
        const zoneDiag1 = this.dataToPoint(data1);
        const zoneDiag2 = this.dataToPoint(data2);
        const area = this.getArea();
        const zone = new BoundingRect(
            zoneDiag1[0],
            zoneDiag1[1],
            zoneDiag2[0] - zoneDiag1[0],
            zoneDiag2[1] - zoneDiag1[1]);
        return area.intersect(zone);
    }

    dataToPoint(data: ScaleDataValue[], clamp?: boolean, out?: number[]): number[] {
        out = out || [];
        const xVal = data[0];
        const yVal = data[1];
        // Fast path
        if (this._transform
            // It's supported that if data is like `[Inifity, 123]`, where only Y pixel calculated.
            && xVal != null
            && isFinite(xVal as number)
            && yVal != null
            && isFinite(yVal as number)
        ) {
            return applyTransform(out, data as number[], this._transform);
        }
        const xAxis = this.getAxis('x');
        const yAxis = this.getAxis('y');
        out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal, clamp));
        out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal, clamp));
        return out;
    }

    clampData(data: ScaleDataValue[], out?: number[]): number[] {
        const xScale = this.getAxis('x').scale;
        const yScale = this.getAxis('y').scale;
        const xAxisExtent = xScale.getExtent();
        const yAxisExtent = yScale.getExtent();
        const x = xScale.parse(data[0]);
        const y = yScale.parse(data[1]);
        out = out || [];
        out[0] = Math.min(
            Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x),
            Math.max(xAxisExtent[0], xAxisExtent[1])
        );
        out[1] = Math.min(
            Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y),
            Math.max(yAxisExtent[0], yAxisExtent[1])
        );

        return out;
    }

    pointToData(point: number[], clamp?: boolean): number[] {
        const out: number[] = [];
        if (this._invTransform) {
            return applyTransform(out, point, this._invTransform);
        }
        const xAxis = this.getAxis('x');
        const yAxis = this.getAxis('y');
        out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp);
        out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp);
        return out;
    }

    getOtherAxis(axis: Axis2D): Axis2D {
        return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
    }

    /**
     * Get rect area of cartesian.
     * Area will have a contain function to determine if a point is in the coordinate system.
     */
    getArea(): Cartesian2DArea {
        const xExtent = this.getAxis('x').getGlobalExtent();
        const yExtent = this.getAxis('y').getGlobalExtent();
        const x = Math.min(xExtent[0], xExtent[1]);
        const y = Math.min(yExtent[0], yExtent[1]);
        const width = Math.max(xExtent[0], xExtent[1]) - x;
        const height = Math.max(yExtent[0], yExtent[1]) - y;

        return new BoundingRect(x, y, width, height);
    }

};

interface Cartesian2DArea extends BoundingRect {}

export default Cartesian2D;
