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 HSpanView extends GlyphView {
    static __name__ = "HSpanView";
    after_visuals() {
        super.after_visuals();
        this.max_line_width = uniforms.max(this.line_width);
    }
    _index_data(index) {
        for (const y_i of this.y) {
            index.add_point(UNUSED, y_i);
        }
    }
    _bounds(bounds) {
        const { y0, y1 } = bounds;
        return { x0: NaN, x1: NaN, y0, y1 };
    }
    _map_data() {
        super._map_data();
        const { round } = Math;
        if (!this.inherited_sy) {
            const sy = map(this.sy, (yi) => round(yi));
            this._define_attr("sy", sy);
        }
    }
    scenterxy(i) {
        const { hcenter } = this.renderer.plot_view.frame.bbox;
        return [hcenter, this.sy[i]];
    }
    _paint(ctx, indices, data) {
        const { sy } = { ...this, ...data };
        const { left, right } = this.renderer.plot_view.frame.bbox;
        for (const i of indices) {
            const sy_i = sy[i];
            if (!isFinite(sy_i)) {
                continue;
            }
            ctx.beginPath();
            ctx.moveTo(left, sy_i);
            ctx.lineTo(right, sy_i);
            this.visuals.line.apply(ctx, i);
        }
    }
    _get_candidates(sy0, sy1) {
        const { max_line_width } = this;
        const [y0, y1] = this.renderer.yscale.r_invert(sy0 - max_line_width, (sy1 ?? sy0) + max_line_width);
        return this.index.indices({ x0: 0, x1: 0, y0, y1 });
    }
    _find_spans(candidates, fn) {
        const { sy, line_width } = this;
        const indices = [];
        for (const i of candidates) {
            const sy_i = sy[i];
            const line_width_i = line_width.get(i);
            if (fn(sy_i, line_width_i)) {
                indices.push(i);
            }
        }
        return indices;
    }
    _hit_point(geometry) {
        const { sy: gsy } = geometry;
        const candidates = this._get_candidates(gsy);
        const indices = this._find_spans(candidates, (sy, line_width) => {
            return abs(sy - gsy) <= max(line_width / 2, 2 /*px*/);
        });
        return new Selection({ indices });
    }
    _hit_span(geometry) {
        const indices = (() => {
            if (geometry.direction == "v") {
                return range(0, this.data_size);
            }
            else {
                const { sy: gsy } = geometry;
                const candidates = this._get_candidates(gsy);
                return this._find_spans(candidates, (sy, line_width) => {
                    return abs(sy - gsy) <= max(line_width / 2, 2 /*px*/);
                });
            }
        })();
        return new Selection({ indices });
    }
    _hit_rect(geometry) {
        const indices = (() => {
            const { sy0: gsy0, sy1: gsy1 } = geometry;
            const candidates = this._get_candidates(gsy0, gsy1);
            return this._find_spans(candidates, (sy, line_width) => {
                return gsy0 - line_width / 2 <= sy && sy <= gsy1 + 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 HSpan extends Glyph {
    static __name__ = "HSpan";
    constructor(attrs) {
        super(attrs);
    }
    static {
        this.prototype.default_view = HSpanView;
        this.mixins([LineVector]);
        this.define(() => ({
            y: [p.YCoordinateSpec, { field: "y" }],
        }));
    }
}
//# sourceMappingURL=hspan.js.map