import { memory } from 'js/types';

export function skipGap(track: memory, start: number = 0): number {
    const end = start + 0x100; // no gap is this big
    let i = start;
    while (i < end && track[i] === 0xFF) {
        i++;
    }
    if (i === end) {
        throw new Error(`found more than 0x100 0xFF bytes after ${start}`);
    }
    return i;
}

export function compareSequences(track: memory, bytes: number[], pos: number): boolean {
    for (let i = 0; i < bytes.length; i++) {
        if (track[i + pos] !== bytes[i]) {
            return false;
        }
    }
    return true;
}

export function expectSequence(track: memory, pos: number, bytes: number[]): number {
    if (!compareSequences(track, bytes, pos)) {
        const track_slice = track.slice(pos, Math.min(track.length, pos + bytes.length));
        throw new Error(`expected ${bytes.toString()} got ${track_slice.toString()}`);
    }
    return pos + bytes.length;
}

export function findBytes(track: memory, bytes: number[], start: number = 0): number {
    if (start + bytes.length > track.length) {
        return -1;
    }
    for (let i = start; i < track.length; i++) {
        if (compareSequences(track, bytes, i)) {
            return i + bytes.length;
        }
    }
    return -1;
}

/**
 * Convert an ASCII character string into an array of bytes, with optional
 * padding.
 *
 * @param val ASCII character string
 * @param pad ASCII character to fill reach padded length
 * @param padLength padded length
 * @returns an array of bytes
 */
export const stringToBytes = (val: string, pad: string = '\0', padLength: number = 0) => {
    const result = [];
    let idx = 0;
    while (idx < val.length) {
        result.push(val.charCodeAt(idx) & 0x7f);
        idx++;
    }
    while (idx++ < padLength) {
        result.push(pad.charCodeAt(0) & 0x7f);
    }
    return result;
};

/**
 * Convert a number into a little endian array of bytes.
 *
 * @param val a number
 * @param count number of bytes in result
 * @returns an array of bytes
 */
export const numberToBytes = (val: number, count: number) => {
    const result = [];
    let idx = 0;
    while (idx < count) {
        result.push(val & 0xff);
        val >>= 8;
        idx++;
    }
    return result;
};
