import { parseLicelProfile } from "./licelprofile";
import { type ILicelFile } from "./licelTypes";
import { latin1Decode, parseDateTime } from "./utils";

const HEADER_LINE_LENGTH = 80;


/**
* Загружает файл Licel из массива байтов.
* @param path - имя файла.
* @returns Объект ILicelFile, содержащий данные измерения.
*/
export async function loadLicelFile(path: string): Promise<ILicelFile> {
    const rawBuffer = await Bun.file(path).arrayBuffer();
    return loadLicelFileFromArrayBuffer(rawBuffer);
}

/**
* Загружает файл Licel из массива байтов.
* @param rawBuffer - Массив байтов.
* @returns Объект ILicelFile, содержащий данные измерения.
*/
export async function loadLicelFileFromArrayBuffer(rawBuffer: ArrayBuffer): Promise<ILicelFile> {
    //const rawBuffer = await Bun.file(path).arrayBuffer();
    const view = new DataView(rawBuffer);

    const header0 = latin1Decode(rawBuffer.slice(0, 80)).trim().split(/\s+/);
    const header1 = latin1Decode(rawBuffer.slice(80, 160)).trim().split(/\s+/);
    const header2 = latin1Decode(rawBuffer.slice(160, 240)).trim().split(/\s+/);



    const measurementStartTime = parseDateTime(`${header1[1]} ${header1[2]}`);
    const measurementStopTime = parseDateTime(`${header1[3]} ${header1[4]}`);

    const licelFile: ILicelFile = {
        measurementSite: header1[0]!,
        measurementStartTime,
        measurementStopTime,
        altitudeAboveSeaLevel: parseFloat(header1[5]!),
        longitude: parseFloat(header1[6]!),
        latitude: parseFloat(header1[7]!),
        zenith: parseFloat(header1[8]!),
        laserConfig: [{
            numberOfShots: parseInt(header2[0]!, 10),
            frequency: parseInt(header2[1]!, 10)
        }, {
            numberOfShots: parseInt(header2[2]!, 10),
            frequency: parseInt(header2[3]!, 10)
        }, {
            numberOfShots: parseInt(header2[5]!, 10),
            frequency: parseInt(header2[6]!, 10)
        }],
        nDatasets: parseInt(header2[4]!, 10),
        profiles: [],
    };

    for (let i = 0; i < licelFile.nDatasets; i++) {
        const profileLine = latin1Decode(rawBuffer.slice((3 + i) * HEADER_LINE_LENGTH, (3 + (i + 1)) * HEADER_LINE_LENGTH)).trim();
        const profile = parseLicelProfile(profileLine);
        licelFile.profiles.push(profile);
    }

    const bytesoffset = (3 + licelFile.nDatasets) * HEADER_LINE_LENGTH + 2;
    let offset = bytesoffset;
    for (let i = 0; i < licelFile.nDatasets; i++) {
        const profileLen = licelFile.profiles![i]!.nDataPoints * 4;

        const profileData = rawBuffer.slice(offset, offset + profileLen);
        const profileDataUInt32 = new Uint32Array(profileData);
        offset += (profileLen + 2);

        licelFile.profiles![i]!.data = profileDataUInt32.map((value) => (value / licelFile.profiles![i]!.nShots));
    }
    return licelFile;
}
