import { type SoundRecordingType } from 'src/data/queries';

// Optimized function to calculate the edit distance (Levenshtein)

const getEditDistance = (s1: string, s2: string): number => {
    if (s1 === s2) return 0;
    if (s1.length === 0) return s2.length;
    if (s2.length === 0) return s1.length;

    let previousRow = Array.from({ length: s2.length + 1 }, (_, i) => i);
    let currentRow = new Array<number>(s2.length + 1);

    for (let i = 1; i <= s1.length; i++) {
        // The first element of the current row is the cost of deleting all characters from s1
        currentRow[0] = i;

        for (let j = 1; j <= s2.length; j++) {
            const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
            currentRow[j] = Math.min(
                previousRow[j] + 1, // Deletion
                currentRow[j - 1] + 1, // Insertion
                previousRow[j - 1] + cost // Substitution
            );
        }

        [previousRow, currentRow] = [currentRow, previousRow];
    }

    return previousRow[s2.length];
};

// Function to sort the tracks array based on similarity to the provided term.
const sortByReference = (
    tracksArray: SoundRecordingType[],
    term: string
): SoundRecordingType[] => {
    const tracksWithDistance = tracksArray.map(track => ({
        track,
        distance: getEditDistance(term, track.name ?? ''),
    }));

    tracksWithDistance.sort((a, b) => a.distance - b.distance);

    return tracksWithDistance.map(item => item.track);
};

export default sortByReference;
