import { Comment, Note } from '../types';
import { getAsciiNoteName, getPitchFromAsciiNoteName } from './utils';

export const regex = /\[(\[.*\],?)*\]/;

export const descriptionOfFormat =
  'The format represents an array of voices. Each voice is an array of strings, expressing the notes in the voice over time. The format of a note is [Length][Pitch]@[Timing]. Lengths are q (quarter note) d (dotted-eighth note) e (eighth note) s (sixteenth note) or t (triplet). Pitches are A-G, followed by an optional # or b for sharp or flat, followed by an octave number. Then we add the delimiter @. Timing is a number of beats (starting from 1).';

export const notesToString = (notes: (Note | Comment)[]): string => {
  const voices = [[]];
  const sorted = ([...notes].filter((n) => n.type !== 'Comment') as Note[]).sort((a, b) => a.start - b.start);
  for (let i = 0; i < sorted.length; i++) {
    const note = sorted[i];
    const roundedStart = Math.round(note.start * 4) / 4;
    const roundedLength = Math.max(0.25, Math.round((note.end - note.start) * 4) / 4);
    const name = getAsciiNoteName(note.pitch);

    let lengthStr = 's';

    if (roundedLength === 0.25) lengthStr = 's';
    if (roundedLength === 0.75) lengthStr = 'd';
    if (roundedLength === 1) lengthStr = 'q';
    if (roundedLength === 0.5) lengthStr = 'e';

    voices[0].push(`${lengthStr}${name}@${roundedStart + 1}`);
  }

  return JSON.stringify(voices);
};

export const stringToNotes = (notes: string): Note[] => {
  const voices = JSON.parse(notes);
  const result: Note[] = [];

  for (let i = 0; i < voices.length; i++) {
    for (let j = 0; j < voices[i].length; j++) {
      const noteStr = voices[i][j];
      if (noteStr.includes('R')) continue; // Rest. shouldn't be part of this but ChatGPT loves em for some reason.
      const length = noteStr[0];
      const beat = noteStr.slice(noteStr.indexOf('@') + 1);
      const pitch = getPitchFromAsciiNoteName(noteStr.slice(1, noteStr.indexOf('@')));
      let startBeats = Number(beat.match(/[0-9]+(\.[0-9]+)?/)[0]) - 1;
      let endBeats = startBeats + 1;

      if (length === 's') endBeats = startBeats + 0.25;
      if (length === 'e') endBeats = startBeats + 0.5;
      if (length === 'd') endBeats = startBeats + 0.75;
      if (length === 'q') endBeats = startBeats + 1;

      result.push({
        pitch,
        start: startBeats,
        end: endBeats,
        velocity: 100 / 127,
      });
    }
  }

  return result;
};
