import { BaseGLGlyph } from "./base";
import { Float32Buffer, NormalizedUint8Buffer, Uint8Buffer } from "./buffer";
import { resolve_line_dash } from "../../../core/visuals/line";
export class BaseLineGL extends BaseGLGlyph {
    glyph;
    static __name__ = "BaseLineGL";
    _antialias = 1.5; // Make this larger to test antialiasing at edges.
    _miter_limit = 10.0; // Threshold for miters to be replaced by bevels.
    // data properties
    _points;
    _show; // Applies to segments not points.
    // visual properties
    _linewidth = new Float32Buffer(this.regl_wrapper);
    _line_color = new NormalizedUint8Buffer(this.regl_wrapper, 4);
    _line_cap = new Uint8Buffer(this.regl_wrapper);
    _line_join = new Uint8Buffer(this.regl_wrapper);
    _is_dashed = false;
    // visual properties that are only used if line is dashed.
    _length_so_far; // Depends on both data and visuals.
    _dash_tex = [];
    _dash_tex_info;
    _dash_scale;
    _dash_offset;
    constructor(regl_wrapper, glyph) {
        super(regl_wrapper, glyph);
        this.glyph = glyph;
    }
    _draw_single(main_gl_glyph, transform, line_offset, point_offset, nsegments, framebuffer, show = null) {
        const solid_props = {
            scissor: this.regl_wrapper.scissor,
            viewport: this.regl_wrapper.viewport,
            canvas_size: [transform.width, transform.height],
            antialias: this._antialias / transform.pixel_ratio,
            miter_limit: this._miter_limit,
            points: main_gl_glyph._points,
            show: show ?? main_gl_glyph._show,
            nsegments,
            linewidth: this._linewidth,
            line_color: this._line_color,
            line_cap: this._line_cap,
            line_join: this._line_join,
            framebuffer,
            point_offset,
            line_offset,
        };
        if (this._is_dashed && this._dash_tex[line_offset] != null) {
            const dashed_props = {
                ...solid_props,
                length_so_far: main_gl_glyph._length_so_far,
                dash_tex: this._dash_tex[line_offset],
                dash_tex_info: this._dash_tex_info,
                dash_scale: this._dash_scale,
                dash_offset: this._dash_offset,
            };
            this.regl_wrapper.dashed_line()(dashed_props);
        }
        else {
            this.regl_wrapper.solid_line()(solid_props);
        }
    }
    _set_length_single(length_so_far, points, show) {
        // Set length so far for a single line from the points and show flags for that line.
        // Only needed if line is dashed.
        const nsegments = length_so_far.length;
        let length = 0.0;
        for (let i = 0; i < nsegments; i++) {
            length_so_far[i] = length;
            if (show[i + 1] == 1) {
                length += Math.sqrt((points[2 * i + 4] - points[2 * i + 2]) ** 2 +
                    (points[2 * i + 5] - points[2 * i + 3]) ** 2);
            }
            else {
                // Reset to zero at invalid point.
                length = 0.0;
            }
        }
    }
    _set_points_single(points, sx, sy) {
        // Set points array for a single line.
        const npoints = points.length / 2 - 2;
        const is_closed = (npoints > 2 && sx[0] == sx[npoints - 1] && sy[0] == sy[npoints - 1] &&
            isFinite(sx[0] + sy[0]));
        for (let i = 1; i < npoints + 1; i++) {
            points[2 * i] = sx[i - 1];
            points[2 * i + 1] = sy[i - 1];
        }
        if (is_closed) {
            points[0] = points[2 * npoints - 2]; // Last but one point.
            points[1] = points[2 * npoints - 1];
            points[2 * npoints + 2] = points[4]; // Second point.
            points[2 * npoints + 3] = points[5];
        }
        else {
            points[0] = 0.0;
            points[1] = 0.0;
            points[2 * npoints + 2] = 0.0;
            points[2 * npoints + 3] = 0.0;
        }
    }
    _set_show_single(show, points) {
        // Set show flags for a single line from the points of that line.
        // Do not show line segments which have a NaN coordinate at either end, and
        // also take account of line being closed (start and end points identical).
        const npoints = points.length / 2 - 2;
        let start_finite = isFinite(points[2] + points[3]);
        for (let i = 1; i < npoints; i++) {
            const end_finite = isFinite(points[2 * i + 2] + points[2 * i + 3]);
            show[i] = (start_finite && end_finite) ? 1 : 0;
            start_finite = end_finite;
        }
        const is_closed = npoints > 2 && points[0] == points[2 * npoints - 2] && points[1] == points[2 * npoints - 1];
        if (is_closed) {
            show[0] = show[npoints - 1];
            show[npoints] = show[1];
        }
        else {
            show[0] = 0;
            show[npoints] = 0;
        }
    }
    _set_visuals() {
        const line_visuals = this._get_visuals();
        this._line_color.set_from_color(line_visuals.line_color, line_visuals.line_alpha);
        this._linewidth.set_from_prop(line_visuals.line_width);
        this._line_cap.set_from_line_cap(line_visuals.line_cap);
        this._line_join.set_from_line_join(line_visuals.line_join);
        const { line_dash } = line_visuals;
        this._is_dashed = !(line_dash.is_Scalar() && line_dash.get(0).length == 0);
        if (this._is_dashed) {
            if (this._dash_offset == null) {
                this._dash_offset = new Float32Buffer(this.regl_wrapper);
            }
            this._dash_offset.set_from_prop(line_visuals.line_dash_offset);
            const n = line_dash.length;
            if (this._dash_tex_info == null) {
                this._dash_tex_info = new Float32Buffer(this.regl_wrapper, 4);
            }
            const dash_tex_info = this._dash_tex_info.get_sized_array(4 * n);
            if (this._dash_scale == null) {
                this._dash_scale = new Float32Buffer(this.regl_wrapper);
            }
            const dash_scale = this._dash_scale.get_sized_array(n);
            // All other dash properties are assumed vector rather than scalar.
            for (let i = 0; i < n; i++) {
                const arr = resolve_line_dash(line_dash.get(i));
                if (arr.length > 0) {
                    // This line is dashed
                    const [tex_info, tex, scale] = this.regl_wrapper.get_dash(arr);
                    this._dash_tex.push(tex);
                    for (let j = 0; j < 4; j++) {
                        dash_tex_info[4 * i + j] = tex_info[j];
                    }
                    dash_scale[i] = scale;
                }
                else {
                    // This line is solid
                    this._dash_tex.push(null);
                    dash_tex_info.fill(0, 4 * i, 4 * (i + 1));
                    dash_scale[i] = 0;
                }
            }
            this._dash_tex_info.update();
            this._dash_scale.update();
        }
    }
}
//# sourceMappingURL=base_line.js.map