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

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

export const descriptionOfFormat =
  'The format represents an array of arrays of notes. Notes are strings. The format of a note is [Length][Pitch]@[Timing]. Lengths are numbers representing a number of quarter notes. 1 = quarter note. 0.25 = sixteenth note. 0.5 = eighth note. 0.75 = dotted eighth note, et cetera. 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 sortedNotes = ([...notes].filter((n) => n.type !== 'Comment') as Note[]).sort((a, b) => a.start - b.start);

  for (let i = 0; i < sortedNotes.length; i++) {
    const note = sortedNotes[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);
    voices[0].push(`${roundedLength}${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.toLowerCase().includes('r')) continue; // Rest. shouldn't be part of this but ChatGPT loves em for some reason.
      console.log(noteStr);
      console.log('length');
      const lengthStr = noteStr.match(/^[0-9]+\.?[0-9]*/)[0];
      if (!Number(lengthStr)) {
        continue;
      }
      console.log('beat');
      const beat = noteStr.match(/@[0-9]+(\.[0-9]+)?/)[0].slice(1);
      console.log('pitch');
      const pitchStr = noteStr.match(/[a-gA-G][#b]?[0-9]+/)[0];
      console.log('Parsed note with', { lengthStr, beat, pitchStr });
      const pitch = getPitchFromAsciiNoteName(pitchStr);
      let startBeats = Number(beat) - 1;
      let endBeats = startBeats + Number(lengthStr);

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

  return result;
};
