import { BaseLineGL } from "./base_line";
import { Float32Buffer, Uint8Buffer } from "./buffer";
export class MultiLineGL extends BaseLineGL {
    glyph;
    static __name__ = "MultiLineGL";
    constructor(regl_wrapper, glyph) {
        super(regl_wrapper, glyph);
        this.glyph = glyph;
    }
    draw(indices, main_glyph, transform) {
        // Indices refer to whole lines not line segments
        if (this.visuals_changed) {
            this._set_visuals();
            this.visuals_changed = false;
        }
        const main_gl_glyph = main_glyph.glglyph;
        const data_changed_or_mapped = main_gl_glyph.data_changed || main_gl_glyph.data_mapped;
        if (data_changed_or_mapped) {
            main_gl_glyph._set_data(main_gl_glyph.data_changed);
        }
        if ((data_changed_or_mapped && main_gl_glyph._is_dashed) || this._is_dashed) {
            // length_so_far is a data property as it depends on point positions in canvas coordinates
            // but is only needed for dashed lines so it also depends on visual properties.
            // Care needed if base glyph is solid but e.g. nonselection glyph is dashed.
            main_gl_glyph._set_length();
        }
        if (data_changed_or_mapped) {
            main_gl_glyph.data_changed = false;
            main_gl_glyph.data_mapped = false;
        }
        const { data_size } = this.glyph; // Number of lines
        let framebuffer = null;
        let tex = null;
        if (data_size > 1) {
            [framebuffer, tex] = this.regl_wrapper.framebuffer_and_texture;
        }
        let point_offset = 0;
        let prev_index = -1;
        for (const index of indices) {
            for (let i = prev_index + 1; i < index; i++) {
                // Account for offsets of lines not displayed
                const npoints = main_glyph.sxs.get(i).length;
                point_offset += (npoints + 2) * 2;
            }
            const npoints = main_glyph.sxs.get(index).length;
            const nsegments = npoints - 1; // Points array includes extra points at each end
            // Not necessary if just a single line
            if (framebuffer != null) {
                this.regl_wrapper.clear_framebuffer(framebuffer);
            }
            this._draw_single(main_gl_glyph, transform, index, point_offset, nsegments, framebuffer);
            if (framebuffer != null) {
                // Accumulate framebuffer to WebGL canvas
                const accumulate_props = {
                    scissor: this.regl_wrapper.scissor,
                    viewport: this.regl_wrapper.viewport,
                    framebuffer_tex: tex,
                };
                this.regl_wrapper.accumulate()(accumulate_props);
            }
            point_offset += (npoints + 2) * 2;
            prev_index = index;
        }
    }
    _get_visuals() {
        return this.glyph.visuals.line;
    }
    _set_data(data_changed) {
        // If data_changed is false the underlying glyph data has not changed but has been mapped to
        // different canvas coordinates e.g. via pan or zoom. If data_changed is true the data itself
        // has changed, which also implies it has been mapped.
        // Set data properties which are points and show flags for data
        // (taking into account NaNs but not selected indices)
        const line_count = this.glyph.data_size;
        const total_point_count = this.glyph.sxs.data.length;
        if (this._points == null) {
            this._points = new Float32Buffer(this.regl_wrapper);
        }
        const points_array = this._points.get_sized_array((total_point_count + 2 * line_count) * 2);
        let point_offset = 0;
        for (let i = 0; i < line_count; i++) {
            // Process a single line at a time.
            const sx = this.glyph.sxs.get(i);
            const sy = this.glyph.sys.get(i);
            const npoints = sx.length;
            const points = points_array.subarray(point_offset, point_offset + (npoints + 2) * 2);
            this._set_points_single(points, sx, sy);
            point_offset += (npoints + 2) * 2;
        }
        this._points.update();
        if (data_changed) {
            if (this._show == null) {
                this._show = new Uint8Buffer(this.regl_wrapper);
            }
            const show_array = this._show.get_sized_array(total_point_count + line_count);
            let point_offset = 0;
            let show_offset = 0;
            for (let i = 0; i < line_count; i++) {
                // Process a single line at a time.
                const sx = this.glyph.sxs.get(i);
                const npoints = sx.length;
                const points = points_array.subarray(point_offset, point_offset + (npoints + 2) * 2);
                const show = show_array.subarray(show_offset, show_offset + npoints + 1);
                this._set_show_single(show, points);
                point_offset += (npoints + 2) * 2;
                show_offset += npoints + 1;
            }
            this._show.update();
        }
    }
    _set_length() {
        const line_count = this.glyph.data_size;
        const total_point_count = this.glyph.sxs.data.length;
        const points_array = this._points.get_array();
        const show_array = this._show.get_array();
        if (this._length_so_far == null) {
            this._length_so_far = new Float32Buffer(this.regl_wrapper);
        }
        const length_so_far = this._length_so_far.get_sized_array(total_point_count - line_count);
        let point_offset = 0;
        let show_offset = 0;
        let length_offset = 0;
        for (let i = 0; i < line_count; i++) {
            const sx = this.glyph.sxs.get(i);
            const npoints = sx.length;
            const nsegments = npoints - 1;
            const points = points_array.subarray(point_offset, point_offset + (npoints + 2) * 2);
            const show = show_array.subarray(show_offset, show_offset + npoints + 1);
            const length = length_so_far.subarray(length_offset, length_offset + nsegments);
            this._set_length_single(length, points, show);
            point_offset += (npoints + 2) * 2;
            show_offset += npoints + 1;
            length_offset += nsegments;
        }
        this._length_so_far.update();
    }
}
//# sourceMappingURL=multi_line.js.map