import { ConfigType } from '../config.js';
import Configurable from '../configurable.js';
export class Row extends Configurable {
    constructor(
    /**
     * The note to play at this row, or null to keep the current note from the previous control line.
     * If this is null from the first control line, the note will be silent.
     */
    note, 
    /**
     * The velocity to play the note at, or null to keep the current velocity from the previous control line.
     * Ranges from 0 to 1
     */
    velocity) {
        super();
        Object.defineProperty(this, "note", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: note
        });
        Object.defineProperty(this, "velocity", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: velocity
        });
        this.note = note;
        this.velocity = velocity;
    }
    get configs() {
        return Row.CONFIGS;
    }
    copyWith({ note, velocity, }) {
        return new Row(note !== undefined ? note : this.note, velocity !== undefined ? velocity : this.velocity);
    }
}
Object.defineProperty(Row, "CONFIGS", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze([
        {
            type: ConfigType.NullableNote,
            default: 'C4',
            field: 'note',
            description: 'Note',
            configurable: true,
        },
        {
            type: ConfigType.NullableNumber,
            default: 0.6,
            min: 0,
            max: 1,
            step: 0.2,
            field: 'velocity',
            description: 'Velocity',
            configurable: true,
        },
    ])
});
export class ControlLine extends Configurable {
    /**
     * Configure playback settings, taking effect at the given column (inclusive)
     * @param column The column at which the settings take effect
     * @param bpm The new beats per minute, or null to keep the current value from the previous control line
     * @param pedal Whether the pedal is pressed, or null to keep the current value from the previous control line
     * @param checkpoint Whether this control line is a checkpoint
     * @param rows The notes to play at each row. This list is automatically resized to match the height of the grid. You may pass in an empty list if none of the rows need to be changed.
     */
    constructor(column, bpm, pedal, checkpoint, rows) {
        super();
        Object.defineProperty(this, "column", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: column
        });
        Object.defineProperty(this, "bpm", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: bpm
        });
        Object.defineProperty(this, "pedal", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: pedal
        });
        Object.defineProperty(this, "checkpoint", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: checkpoint
        });
        Object.defineProperty(this, "rows", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: rows
        });
        this.column = Math.floor(column);
        this.bpm = bpm;
        this.pedal = pedal;
        this.checkpoint = checkpoint;
        this.rows = rows;
    }
    get configs() {
        return ControlLine.CONFIGS;
    }
    copyWith({ column, bpm, pedal, checkpoint, rows, }) {
        return new ControlLine(column ?? this.column, bpm !== undefined ? bpm : this.bpm, pedal !== undefined ? pedal : this.pedal, checkpoint ?? this.checkpoint, rows ?? this.rows);
    }
    withColumn(column) {
        return this.copyWith({ column });
    }
    withBpm(bpm) {
        return this.copyWith({ bpm });
    }
    withPedal(pedal) {
        return this.copyWith({ pedal });
    }
    withCheckpoint(checkpoint) {
        return this.copyWith({ checkpoint });
    }
    withRows(rows) {
        return this.copyWith({ rows });
    }
    equals(other) {
        return (this.column === other.column &&
            this.bpm === other.bpm &&
            this.pedal === other.pedal &&
            this.checkpoint === other.checkpoint &&
            this.rows.length === other.rows.length &&
            this.rows.every((row, i) => {
                const otherRow = other.rows[i];
                return row.note === otherRow.note && row.velocity === otherRow.velocity;
            }));
    }
    get isEmpty() {
        return (this.bpm === null &&
            this.pedal === null &&
            !this.checkpoint &&
            !this.rows.some(row => row.note !== null || row.velocity !== null));
    }
}
Object.defineProperty(ControlLine, "CONFIGS", {
    enumerable: true,
    configurable: true,
    writable: true,
    value: Object.freeze([
        {
            type: ConfigType.NullableNumber,
            default: 120,
            min: 20,
            max: 1000,
            field: 'bpm',
            description: 'BPM',
            configurable: true,
        },
        {
            type: ConfigType.NullableBoolean,
            default: false,
            field: 'pedal',
            description: 'Pedal',
            configurable: true,
        },
        {
            type: ConfigType.Boolean,
            default: false,
            field: 'checkpoint',
            description: 'Checkpoint',
            configurable: true,
        },
    ])
});
export const instance = undefined;
