import { XYGlyph, XYGlyphView } from "./xy_glyph";
import { inherit } from "./glyph";
import { to_screen } from "../../core/types";
import { LineVector, FillVector, HatchVector } from "../../core/property_mixins";
import * as p from "../../core/properties";
import { Selection } from "../selections/selection";
export class AnnulusView extends XYGlyphView {
    static __name__ = "AnnulusView";
    async load_glglyph() {
        const { AnnulusGL } = await import("./webgl/annulus");
        return AnnulusGL;
    }
    _map_data() {
        this._define_or_inherit_attr("sinner_radius", () => {
            if (this.model.properties.inner_radius.units == "data") {
                if (this.inherited_x && this.inherited_inner_radius) {
                    return inherit;
                }
                else {
                    return this.sdist(this.renderer.xscale, this.x, this.inner_radius);
                }
            }
            else {
                return this.inherited_inner_radius ? inherit : to_screen(this.inner_radius);
            }
        });
        this._define_or_inherit_attr("souter_radius", () => {
            if (this.model.properties.outer_radius.units == "data") {
                if (this.inherited_x && this.inherited_outer_radius) {
                    return inherit;
                }
                else {
                    return this.sdist(this.renderer.xscale, this.x, this.outer_radius);
                }
            }
            else {
                return this.inherited_outer_radius ? inherit : to_screen(this.outer_radius);
            }
        });
    }
    _paint(ctx, indices, data) {
        const { sx, sy, sinner_radius, souter_radius } = { ...this, ...data };
        for (const i of indices) {
            const sx_i = sx[i];
            const sy_i = sy[i];
            const sinner_radius_i = sinner_radius[i];
            const souter_radius_i = souter_radius[i];
            if (!isFinite(sx_i + sy_i + sinner_radius_i + souter_radius_i)) {
                continue;
            }
            ctx.beginPath();
            ctx.arc(sx_i, sy_i, sinner_radius_i, 0, 2 * Math.PI, true);
            ctx.moveTo(sx_i + souter_radius_i, sy_i);
            ctx.arc(sx_i, sy_i, souter_radius_i, 2 * Math.PI, 0, false);
            this.visuals.fill.apply(ctx, i);
            this.visuals.hatch.apply(ctx, i);
            this.visuals.line.apply(ctx, i);
        }
    }
    _hit_point(geometry) {
        const { sx, sy } = geometry;
        const x = this.renderer.xscale.invert(sx);
        const y = this.renderer.yscale.invert(sy);
        let x0, y0;
        let x1, y1;
        if (this.model.properties.outer_radius.units == "data") {
            x0 = x - this.max_outer_radius;
            x1 = x + this.max_outer_radius;
            y0 = y - this.max_outer_radius;
            y1 = y + this.max_outer_radius;
        }
        else {
            const sx0 = sx - this.max_outer_radius;
            const sx1 = sx + this.max_outer_radius;
            [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1);
            const sy0 = sy - this.max_outer_radius;
            const sy1 = sy + this.max_outer_radius;
            [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1);
        }
        const indices = [];
        for (const i of this.index.indices({ x0, x1, y0, y1 })) {
            const or2 = this.souter_radius[i] ** 2;
            const ir2 = this.sinner_radius[i] ** 2;
            const [sx0, sx1] = this.renderer.xscale.r_compute(x, this.x[i]);
            const [sy0, sy1] = this.renderer.yscale.r_compute(y, this.y[i]);
            const dist = (sx0 - sx1) ** 2 + (sy0 - sy1) ** 2;
            if (dist <= or2 && dist >= ir2) {
                indices.push(i);
            }
        }
        return new Selection({ indices });
    }
    draw_legend_for_index(ctx, { x0, y0, x1, y1 }, index) {
        const len = index + 1;
        const sx = new Array(len);
        sx[index] = (x0 + x1) / 2;
        const sy = new Array(len);
        sy[index] = (y0 + y1) / 2;
        const r = Math.min(Math.abs(x1 - x0), Math.abs(y1 - y0)) * 0.5;
        const sinner_radius = new Array(len);
        sinner_radius[index] = r * 0.4;
        const souter_radius = new Array(len);
        souter_radius[index] = r * 0.8;
        this._paint(ctx, [index], { sx, sy, sinner_radius, souter_radius });
    }
}
export class Annulus extends XYGlyph {
    static __name__ = "Annulus";
    constructor(attrs) {
        super(attrs);
    }
    static {
        this.prototype.default_view = AnnulusView;
        this.mixins([LineVector, FillVector, HatchVector]);
        this.define(({}) => ({
            inner_radius: [p.DistanceSpec, { field: "inner_radius" }],
            outer_radius: [p.DistanceSpec, { field: "outer_radius" }],
        }));
    }
}
//# sourceMappingURL=annulus.js.map