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

export const regex = /\[(\"([A-G][#b]?[0-9]+)+\s[0-9]+\s[0-9]+\",?)*\]/;

export const descriptionOfFormat =
  'a list of pitches, followed by the start beat, and then the length of time that the note is held. 1 means hold the note for the full quarter note. 0.5 means hold it for only an eighth note.';

export const notesToString = (notes: (Note | Comment)[]): string => {
  const byStartAndLength: { [key: string]: string[] } = {};
  for (let i = 0; i < notes.length; i++) {
    const note = notes[i];
    if (note.type === 'Comment') continue;
    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);
    if (!byStartAndLength[`${roundedStart}:${roundedLength}`]) {
      byStartAndLength[`${roundedStart}:${roundedLength}`] = [];
    }
    byStartAndLength[`${roundedStart}:${roundedLength}`].push(name);
  }

  const result: string[] = [];
  Object.keys(byStartAndLength)
    .sort((a, b) => (Number(a.split(':')[0]) < Number(b.split(':')[0]) ? -1 : 1))
    .forEach((key) => {
      result.push(`${byStartAndLength[key].join(' ')} ${key.split(':').join(' ')}`);
    });
  return `["${result.join('", "')}"]`;
};

export const stringToNotes = (notes: string): Note[] => {
  const noteStrings = JSON.parse(notes);
  const result: Note[] = [];
  for (let i = 0; i < noteStrings.length; i++) {
    const note = noteStrings[i];
    const [start, length] = note.split(' ').slice(-2);
    const pitches = note.split(' ').slice(0, -2);
    pitches.forEach((p) => {
      const pitch = getPitchFromAsciiNoteName(p);
      const startBeats = Number(start);
      const endBeats = Number(start) + Number(length);

      if (pitch === undefined || isNaN(startBeats) || isNaN(endBeats) || isNaN(pitch)) return;

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