import { Beam } from './beam.js';
import { Formatter } from './formatter.js';
import { Modifier } from './modifier.js';
import { StaveNote } from './stavenote.js';
import { StaveTie } from './stavetie.js';
import { Tables } from './tables.js';
import { TabTie } from './tabtie.js';
import { isStaveNote } from './typeguard.js';
import { log } from './util.js';
import { Voice } from './voice.js';
function L(...args) {
    if (GraceNoteGroup.DEBUG)
        log('Vex.Flow.GraceNoteGroup', args);
}
class GraceNoteGroup extends Modifier {
    static get CATEGORY() {
        return "GraceNoteGroup";
    }
    static format(gracenote_groups, state) {
        const group_spacing_stave = 4;
        const group_spacing_tab = 0;
        if (!gracenote_groups || gracenote_groups.length === 0)
            return false;
        const group_list = [];
        let prev_note = null;
        let shiftL = 0;
        for (let i = 0; i < gracenote_groups.length; ++i) {
            const gracenote_group = gracenote_groups[i];
            const note = gracenote_group.getNote();
            const is_stavenote = isStaveNote(note);
            const spacing = is_stavenote ? group_spacing_stave : group_spacing_tab;
            if (is_stavenote && note !== prev_note) {
                for (let n = 0; n < note.keys.length; ++n) {
                    shiftL = Math.max(note.getLeftDisplacedHeadPx(), shiftL);
                }
                prev_note = note;
            }
            group_list.push({ shift: shiftL, gracenote_group, spacing });
        }
        let group_shift = group_list[0].shift;
        let formatWidth;
        for (let i = 0; i < group_list.length; ++i) {
            const gracenote_group = group_list[i].gracenote_group;
            gracenote_group.preFormat();
            formatWidth = gracenote_group.getWidth() + group_list[i].spacing;
            group_shift = Math.max(formatWidth, group_shift);
        }
        for (let i = 0; i < group_list.length; ++i) {
            const gracenote_group = group_list[i].gracenote_group;
            formatWidth = gracenote_group.getWidth() + group_list[i].spacing;
            gracenote_group.setSpacingFromNextModifier(group_shift - Math.min(formatWidth, group_shift) + StaveNote.minNoteheadPadding);
        }
        state.left_shift += group_shift;
        return true;
    }
    constructor(grace_notes, show_slur) {
        super();
        this.preFormatted = false;
        this.position = Modifier.Position.LEFT;
        this.grace_notes = grace_notes;
        this.width = 0;
        this.show_slur = show_slur;
        this.slur = undefined;
        this.voice = new Voice({
            num_beats: 4,
            beat_value: 4,
            resolution: Tables.RESOLUTION,
        }).setStrict(false);
        this.render_options = {
            slur_y_shift: 0,
        };
        this.beams = [];
        this.voice.addTickables(this.grace_notes);
        return this;
    }
    preFormat() {
        if (this.preFormatted)
            return;
        if (!this.formatter) {
            this.formatter = new Formatter();
        }
        this.formatter.joinVoices([this.voice]).format([this.voice], 0, {});
        this.setWidth(this.formatter.getMinTotalWidth());
        this.preFormatted = true;
    }
    beamNotes(grace_notes) {
        grace_notes = grace_notes || this.grace_notes;
        if (grace_notes.length > 1) {
            const beam = new Beam(grace_notes);
            beam.render_options.beam_width = 3;
            beam.render_options.partial_beam_length = 4;
            this.beams.push(beam);
        }
        return this;
    }
    setWidth(width) {
        this.width = width;
        return this;
    }
    getWidth() {
        return this.width + StaveNote.minNoteheadPadding;
    }
    getGraceNotes() {
        return this.grace_notes;
    }
    draw() {
        const ctx = this.checkContext();
        const note = this.checkAttachedNote();
        this.setRendered();
        L('Drawing grace note group for:', note);
        this.alignSubNotesWithNote(this.getGraceNotes(), note);
        this.grace_notes.forEach((graceNote) => graceNote.setContext(ctx).draw());
        this.beams.forEach((beam) => beam.setContext(ctx).draw());
        if (this.show_slur) {
            const is_stavenote = isStaveNote(note);
            const TieClass = is_stavenote ? StaveTie : TabTie;
            this.slur = new TieClass({
                last_note: this.grace_notes[0],
                first_note: note,
                first_indices: [0],
                last_indices: [0],
            });
            this.slur.render_options.cp2 = 12;
            this.slur.render_options.y_shift = (is_stavenote ? 7 : 5) + this.render_options.slur_y_shift;
            this.slur.setContext(ctx).draw();
        }
    }
}
GraceNoteGroup.DEBUG = false;
export { GraceNoteGroup };
//# sourceMappingURL=gracenotegroup.js.map