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]. 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. For a rest, add "R0" instead of a pitch name. You can tell how far you are in the clip by adding up the lengths of each note.';

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 nextNote = sortedNotes[i + 1];
    const roundedLength = Math.max(0.25, Math.round((note.end - note.start) * 4) / 4);
    const timeToNextNote = nextNote ? Math.max(Math.round(nextNote.start * 4) / 4 - roundedStart, 0.25) : 1;
    const name = getAsciiNoteName(note.pitch);
    voices[0].push(`${roundedLength}${name}`);
    if (timeToNextNote > roundedLength) {
      voices[0].push(`${timeToNextNote - roundedLength}R0`);
    }
  }

  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++) {
    let offset = 0;
    for (let j = 0; j < voices[i].length; j++) {
      const noteStr = voices[i][j];
      console.log(noteStr);

      console.log('length');
      const lengthStr = noteStr.match(/^[0-9]+\.?[0-9]*/)[0];

      console.log('pitch');
      const pitchStr = noteStr.match(/[a-gA-GrR][#b]?[0-9]+/)[0];

      console.log('Parsed note with', { lengthStr, pitchStr });
      const length = Number(lengthStr);

      let startBeats = offset;
      offset += length;
      let endBeats = offset;

      if (pitchStr.toLowerCase().includes('r')) continue;
      const pitch = getPitchFromAsciiNoteName(pitchStr);

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

  return result;
};
