/*
* 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 RadiusAxis from './RadiusAxis';
import AngleAxis from './AngleAxis';
import PolarModel from './PolarModel';
import { CoordinateSystem, CoordinateSystemMaster, CoordinateSystemClipArea } from '../CoordinateSystem';
import GlobalModel from '../../model/Global';
import { ParsedModelFinder, ParsedModelFinderKnown } from '../../util/model';
import { ScaleDataValue } from '../../util/types';
import ExtensionAPI from '../../core/ExtensionAPI';

export const polarDimensions = ['radius', 'angle'];

interface Polar {
    update(ecModel: GlobalModel, api: ExtensionAPI): void
}
class Polar implements CoordinateSystem, CoordinateSystemMaster {

    readonly name: string;

    readonly dimensions = polarDimensions;

    readonly type = 'polar';

    /**
     * x of polar center
     */
    cx = 0;

    /**
     * y of polar center
     */
    cy = 0;

    private _radiusAxis = new RadiusAxis();

    private _angleAxis = new AngleAxis();

    axisPointerEnabled = true;

    model: PolarModel;

    constructor(name: string) {
        this.name = name || '';

        this._radiusAxis.polar = this._angleAxis.polar = this;
    }

    /**
     * If contain coord
     */
    containPoint(point: number[]) {
        const coord = this.pointToCoord(point);
        return this._radiusAxis.contain(coord[0])
            && this._angleAxis.contain(coord[1]);
    }

    /**
     * If contain data
     */
    containData(data: number[]) {
        return this._radiusAxis.containData(data[0])
            && this._angleAxis.containData(data[1]);
    }

    getAxis(dim: 'radius' | 'angle') {
        const key = ('_' + dim + 'Axis') as '_radiusAxis' | '_angleAxis';
        return this[key];
    }

    getAxes() {
        return [this._radiusAxis, this._angleAxis];
    }

    /**
     * Get axes by type of scale
     */
    getAxesByScale(scaleType: 'ordinal' | 'interval' | 'time' | 'log') {
        const axes = [];
        const angleAxis = this._angleAxis;
        const radiusAxis = this._radiusAxis;
        angleAxis.scale.type === scaleType && axes.push(angleAxis);
        radiusAxis.scale.type === scaleType && axes.push(radiusAxis);

        return axes;
    }

    getAngleAxis() {
        return this._angleAxis;
    }

    getRadiusAxis() {
        return this._radiusAxis;
    }

    getOtherAxis(axis: AngleAxis | RadiusAxis): AngleAxis | RadiusAxis {
        const angleAxis = this._angleAxis;
        return axis === angleAxis ? this._radiusAxis : angleAxis;
    }

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

    getTooltipAxes(dim: 'radius' | 'angle' | 'auto') {
        const baseAxis = (dim != null && dim !== 'auto')
            ? this.getAxis(dim) : this.getBaseAxis();
        return {
            baseAxes: [baseAxis],
            otherAxes: [this.getOtherAxis(baseAxis)]
        };
    }

    /**
     * Convert a single data item to (x, y) point.
     * Parameter data is an array which the first element is radius and the second is angle
     */
    dataToPoint(data: ScaleDataValue[], clamp?: boolean) {
        return this.coordToPoint([
            this._radiusAxis.dataToRadius(data[0], clamp),
            this._angleAxis.dataToAngle(data[1], clamp)
        ]);
    }

    /**
     * Convert a (x, y) point to data
     */
    pointToData(point: number[], clamp?: boolean) {
        const coord = this.pointToCoord(point);
        return [
            this._radiusAxis.radiusToData(coord[0], clamp),
            this._angleAxis.angleToData(coord[1], clamp)
        ];
    }

    /**
     * Convert a (x, y) point to (radius, angle) coord
     */
    pointToCoord(point: number[]) {
        let dx = point[0] - this.cx;
        let dy = point[1] - this.cy;
        const angleAxis = this.getAngleAxis();
        const extent = angleAxis.getExtent();
        let minAngle = Math.min(extent[0], extent[1]);
        let maxAngle = Math.max(extent[0], extent[1]);
        // Fix fixed extent in polarCreator
        // FIXME
        angleAxis.inverse
            ? (minAngle = maxAngle - 360)
            : (maxAngle = minAngle + 360);

        const radius = Math.sqrt(dx * dx + dy * dy);
        dx /= radius;
        dy /= radius;

        let radian = Math.atan2(-dy, dx) / Math.PI * 180;

        // move to angleExtent
        const dir = radian < minAngle ? 1 : -1;
        while (radian < minAngle || radian > maxAngle) {
            radian += dir * 360;
        }

        return [radius, radian];
    }

    /**
     * Convert a (radius, angle) coord to (x, y) point
     */
    coordToPoint(coord: number[]) {
        const radius = coord[0];
        const radian = coord[1] / 180 * Math.PI;
        const x = Math.cos(radian) * radius + this.cx;
        // Inverse the y
        const y = -Math.sin(radian) * radius + this.cy;

        return [x, y];
    }

    /**
     * Get ring area of cartesian.
     * Area will have a contain function to determine if a point is in the coordinate system.
     */
    getArea(): PolarArea {

        const angleAxis = this.getAngleAxis();
        const radiusAxis = this.getRadiusAxis();

        const radiusExtent = radiusAxis.getExtent().slice();
        radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse();
        const angleExtent = angleAxis.getExtent();

        const RADIAN = Math.PI / 180;

        return {
            cx: this.cx,
            cy: this.cy,
            r0: radiusExtent[0],
            r: radiusExtent[1],
            startAngle: -angleExtent[0] * RADIAN,
            endAngle: -angleExtent[1] * RADIAN,
            clockwise: angleAxis.inverse,
            contain(x: number, y: number) {
                // It's a ring shape.
                // Start angle and end angle don't matter
                const dx = x - this.cx;
                const dy = y - this.cy;
                // minus a tiny value 1e-4 to avoid being clipped unexpectedly
                const d2 = dx * dx + dy * dy - 1e-4;
                const r = this.r;
                const r0 = this.r0;

                return d2 <= r * r && d2 >= r0 * r0;
            }
        };
    }

    convertToPixel(ecModel: GlobalModel, finder: ParsedModelFinder, value: ScaleDataValue[]) {
        const coordSys = getCoordSys(finder);
        return coordSys === this ? this.dataToPoint(value) : null;
    }

    convertFromPixel(ecModel: GlobalModel, finder: ParsedModelFinder, pixel: number[]) {
        const coordSys = getCoordSys(finder);
        return coordSys === this ? this.pointToData(pixel) : null;
    }
}

function getCoordSys(finder: ParsedModelFinderKnown) {
    const seriesModel = finder.seriesModel;
    const polarModel = finder.polarModel as PolarModel;
    return polarModel && polarModel.coordinateSystem
        || seriesModel && seriesModel.coordinateSystem as Polar;
}

interface PolarArea extends CoordinateSystemClipArea {
    cx: number
    cy: number
    r0: number
    r: number
    startAngle: number
    endAngle: number
    clockwise: boolean
}

export default Polar;
