import { Glyph, GlyphView } from "./glyph";
import { generic_line_vector_legend } from "./utils";
import { Selection } from "../selections/selection";
import { LineVector } from "../../core/property_mixins";
import * as uniforms from "../../core/uniforms";
import { map } from "../../core/util/arrayable";
import { range } from "../../core/util/array";
import * as p from "../../core/properties";
const { abs, max } = Math;
const UNUSED = 0;
export class VSpanView extends GlyphView {
    static __name__ = "VSpanView";
    after_visuals() {
        super.after_visuals();
        this.max_line_width = uniforms.max(this.line_width);
    }
    _index_data(index) {
        for (const x_i of this.x) {
            index.add_point(x_i, UNUSED);
        }
    }
    _bounds(bounds) {
        const { x0, x1 } = bounds;
        return { x0, x1, y0: NaN, y1: NaN };
    }
    _map_data() {
        super._map_data();
        const { round } = Math;
        if (!this.inherited_sx) {
            const sx = map(this.sx, (xi) => round(xi));
            this._define_attr("sx", sx);
        }
    }
    scenterxy(i) {
        const { vcenter } = this.renderer.plot_view.frame.bbox;
        return [this.sx[i], vcenter];
    }
    _paint(ctx, indices, data) {
        const { sx } = { ...this, ...data };
        const { top, bottom } = this.renderer.plot_view.frame.bbox;
        for (const i of indices) {
            const sx_i = sx[i];
            if (!isFinite(sx_i)) {
                continue;
            }
            ctx.beginPath();
            ctx.moveTo(sx_i, top);
            ctx.lineTo(sx_i, bottom);
            this.visuals.line.apply(ctx, i);
        }
    }
    _get_candidates(sx0, sx1) {
        const { max_line_width } = this;
        const [x0, x1] = this.renderer.xscale.r_invert(sx0 - max_line_width, (sx1 ?? sx0) + max_line_width);
        return this.index.indices({ x0, x1, y0: 0, y1: 0 });
    }
    _find_spans(candidates, fn) {
        const { sx, line_width } = this;
        const indices = [];
        for (const i of candidates) {
            const sx_i = sx[i];
            const line_width_i = line_width.get(i);
            if (fn(sx_i, line_width_i)) {
                indices.push(i);
            }
        }
        return indices;
    }
    _hit_point(geometry) {
        const { sx: gsx } = geometry;
        const candidates = this._get_candidates(gsx);
        const indices = this._find_spans(candidates, (sx, line_width) => {
            return abs(sx - gsx) <= max(line_width, 2 /*px*/);
        });
        return new Selection({ indices });
    }
    _hit_span(geometry) {
        const indices = (() => {
            if (geometry.direction == "h") {
                return range(0, this.data_size);
            }
            else {
                const { sx: gsx } = geometry;
                const candidates = this._get_candidates(gsx);
                return this._find_spans(candidates, (sx, line_width) => {
                    return abs(sx - gsx) <= max(line_width / 2, 2 /*px*/);
                });
            }
        })();
        return new Selection({ indices });
    }
    _hit_rect(geometry) {
        const indices = (() => {
            const { sx0: gsx0, sx1: gsx1 } = geometry;
            const candidates = this._get_candidates(gsx0, gsx1);
            return this._find_spans(candidates, (sx, line_width) => {
                return gsx0 - line_width / 2 <= sx && sx <= gsx1 + line_width / 2;
            });
        })();
        return new Selection({ indices });
    }
    draw_legend_for_index(ctx, bbox, index) {
        generic_line_vector_legend(this.visuals, ctx, bbox, index);
    }
}
export class VSpan extends Glyph {
    static __name__ = "VSpan";
    constructor(attrs) {
        super(attrs);
    }
    static {
        this.prototype.default_view = VSpanView;
        this.mixins([LineVector]);
        this.define(() => ({
            x: [p.XCoordinateSpec, { field: "x" }],
        }));
    }
}
//# sourceMappingURL=vspan.js.map