"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doSelect = exports.setupPickFiles = void 0;
const fs = require("fs");
const path = require("path");
const busy_context_utils_1 = require("./busy-context-utils");
const filestoreName = '__oj_filepicker_files';
const filenamePrefix = 'file_';
/**
 * This method should be called right before ojfilepickerutils.pickFiles
 * Takes the webdriver and an Array of objects containing file paths + types.
 * These files will be read from the local filesystem and then sent
 * to the pickFiles method to simulate user file selection. Only the basename of
 * the file will be sent, not the entire path to make it consistent with how
 * the browser sets the value.
 * @param driver the Webdriver of the test
 * @param files An array of objects containing the path and type of selected files
 */
const setupPickFiles = async (driver, files) => {
    await (0, busy_context_utils_1.whenBusyContextReady)(driver);
    //create a buffer with the files
    const dataList = files.map(({ path: filePath, type }) => {
        const fileSizeInMB = fs.statSync(filePath).size / (1024 * 1024);
        // webdriver has limit of 8MB per transfer; split file into 8MB chunks
        const numberChunks = Math.ceil(fileSizeInMB / 8);
        const fileContent = Array.from(fs.readFileSync(filePath));
        const chunkSize = Math.floor(fileContent.length / numberChunks);
        const fileChunks = [];
        for (let i = 0; i < numberChunks; i++) {
            if (i + 1 == numberChunks) {
                fileChunks.push(fileContent.slice(i * chunkSize));
            }
            else {
                fileChunks.push(fileContent.slice(i * chunkSize, (i + 1) * chunkSize));
            }
        }
        return {
            bytes: fileChunks, //split it into 8MB chunks
            path: path.basename(filePath),
            type,
            numberChunks
        };
    });
    for (let i = 0; i < dataList.length; i++) {
        const { bytes, path, type, numberChunks } = dataList[i];
        for (let j = 0; j < bytes.length; j++) {
            const file = {
                bytes: bytes[j],
                path,
                type,
                numberChunks,
                chunkNumber: j,
                fileNumber: i
            };
            await driver.executeScript((file, filestoreName, filenamePrefix) => {
                // create the filestore object if not already exists
                const filestore = (window[filestoreName] =
                    window[filestoreName] || {});
                const chunkNumber = file.chunkNumber;
                const data = {
                    bytes: file.bytes,
                    path: file.path,
                    type: file.type
                };
                const fileKey = filenamePrefix + file.fileNumber;
                if (chunkNumber == 0) {
                    filestore[fileKey] = [data];
                }
                else {
                    filestore[fileKey].push(data);
                }
            }, file, filestoreName, filenamePrefix);
        }
    }
    driver.executeScript((numFiles, filestoreName, filenamePrefix) => {
        const filestore = window[filestoreName];
        const list = [];
        for (let i = 0; i < numFiles; i++) {
            const fileKey = filenamePrefix + i;
            const chunks = filestore[fileKey];
            delete filestore[fileKey];
            list.push({
                bytes: chunks.reduce((acc, chunk) => acc.concat(chunk.bytes), []),
                path: chunks[0].path,
                type: chunks[0].type
            });
        }
        const fileList = list.map((data) => {
            return new File([Uint8Array.from(data.bytes)], data.path, { type: data.type });
        });
        // Only if setupPickFiles has not been called yet
        if (!HTMLInputElement.prototype._pickerTestData) {
            //Save the native click method
            const clickMethod = HTMLInputElement.prototype.click;
            //Overwrite the click method
            HTMLInputElement.prototype.click = function () {
                const event = new CustomEvent('change');
                this.dispatchEvent(event);
                delete HTMLInputElement.prototype._pickerTestData;
                HTMLInputElement.prototype.click = clickMethod;
            };
        }
        HTMLInputElement.prototype._pickerTestData = fileList;
    }, dataList.length, filestoreName, filenamePrefix);
};
exports.setupPickFiles = setupPickFiles;
/**
 * Takes an Array of objects containing file paths + types.
 * These files will be read from the local filesystem and then sent
 * to the oj-file-picker to simulate user file selection. Only the basename of
 * the file will be sent, not the entire path to make it consistent with how
 * the browser sets the value.
 * @param picker The file picker element
 * @param files An array of objects containing the path and type of selected files
 */
const doSelect = async (picker, files) => {
    const driver = picker.getDriver();
    await (0, exports.setupPickFiles)(driver, files);
    await driver.executeScript((el) => el.firstChild.click(), picker);
    return (0, busy_context_utils_1.whenBusyContextReady)(driver);
};
exports.doSelect = doSelect;
//# sourceMappingURL=file-picker-utils.js.map