"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deleteOldDependencies = exports.updateResourcesForOneDependency = exports.getDatatablesResourceInformation = exports.getCdnjsResourceInformation = exports.downloadResource = exports.downloadFile = void 0;
const fse = __importStar(require("fs-extra"));
const https = __importStar(require("https"));
const path = __importStar(require("path"));
const axios_1 = __importDefault(require("axios"));
const semver_1 = __importDefault(require("semver"));
const ssri_1 = __importDefault(require("ssri"));
const downloadFile = async (url, filePath) => new Promise((resolve, reject) => {
    https.get(url, response => {
        const statusCode = response.statusCode;
        if (statusCode !== 200) {
            reject(new Error('Download error!'));
            return;
        }
        const writeStream = fse.createWriteStream(filePath);
        response.pipe(writeStream);
        writeStream.on('error', () => {
            reject(new Error('Error writing to file!'));
        });
        writeStream.on('finish', () => {
            writeStream.close();
            resolve(true);
        });
    });
}).catch(err => {
    if (err.message.includes('Download error!')) {
        console.log(`error downloading file ${url}`);
    }
    else {
        console.log(err.message);
    }
    return false;
});
exports.downloadFile = downloadFile;
const downloadResource = async (destinationPath, url) => {
    if (!fse.existsSync(destinationPath)) {
        fse.mkdirSync(path.dirname(destinationPath), { recursive: true });
        const downloadResult = await (0, exports.downloadFile)(url, destinationPath);
        return downloadResult;
    }
    return false;
};
exports.downloadResource = downloadResource;
const getCdnjsResourceInformation = async (dependency, resourcesFolder) => {
    const resourceUrl = `https://api.cdnjs.com/libraries/${dependency.name}?fields=name,version,repository,assets,latest,name,filename`;
    let response = {};
    try {
        response = (await axios_1.default.get(resourceUrl)).data;
    }
    catch (error) {
        console.log(`error ${error.message} in function getCdnjsResourceInformation with dependency ${dependency.name}`);
    }
    const filePropertiesArray = [];
    if (semver_1.default.gt(response.version, dependency.version)) {
        try {
            await Promise.all(dependency.files.map(async (file) => {
                const destinationPath = path.join(resourcesFolder, `${dependency.name}-${response.version}`, file.name);
                const url = response.latest.replace(response.filename, file.name);
                await (0, exports.downloadResource)(destinationPath, url);
                const fileProperties = {
                    name: file.name,
                    path: destinationPath,
                    sriValue: response.assets[response.assets.length - 1].sri[file.name],
                    url
                };
                filePropertiesArray.push(fileProperties);
            }));
        }
        catch (error) {
            console.log(`error ${error.message} in function getCdnjsResourceInformation with dependency ${dependency.name}`);
        }
    }
    return {
        name: dependency.name,
        files: filePropertiesArray,
        version: response.version
    };
};
exports.getCdnjsResourceInformation = getCdnjsResourceInformation;
const getDatatablesResourceInformation = async (dependency, resourcesFolder) => {
    const resourceUrl = 'https://datatables.net/feeds/versions';
    let response = {};
    try {
        response = (await axios_1.default.get(resourceUrl)).data;
    }
    catch (error) {
        console.log(`error ${error.message} in function getDatatablesResourceInformation with dependency ${dependency.name}`);
    }
    const filePropertiesArray = [];
    try {
        await Promise.all(dependency.files.map(async (file) => {
            const destinationPath = path.join(resourcesFolder, `${dependency.name}-${response[dependency.name].release.version}`, file.name);
            const url = file.url?.replace(dependency.version, response[dependency.name].release.version);
            const fileDownloaded = await (0, exports.downloadResource)(destinationPath, url);
            const fileProperties = {
                name: file.name,
                path: destinationPath,
                sriValue: fileDownloaded ? ssri_1.default.fromData(fse.readFileSync(destinationPath)).toString() : '',
                url
            };
            if (fileDownloaded) {
                filePropertiesArray.push(fileProperties);
            }
        }));
    }
    catch (error) {
        console.log(`error ${error.message} in function getDatatablesResourceInformation with dependency ${dependency.name}`);
    }
    return {
        name: dependency.name,
        files: filePropertiesArray,
        version: response[dependency.name].release.version
    };
};
exports.getDatatablesResourceInformation = getDatatablesResourceInformation;
const updateResourcesForOneDependency = async (resourceProperties, resourcesFolder, templateFiles) => {
    const resourceInformation = resourceProperties.cdn === 'cdnjs' ?
        await (0, exports.getCdnjsResourceInformation)(resourceProperties, resourcesFolder) :
        await (0, exports.getDatatablesResourceInformation)(resourceProperties, resourcesFolder);
    if (resourceInformation.version && semver_1.default.gt(resourceInformation.version, resourceProperties.version)) {
        await Promise.all(templateFiles.map(async (templateFile) => {
            let templateFileContent = await fse.readFile(templateFile, { encoding: 'utf8' });
            if (resourceInformation.files.length) {
                resourceInformation.files.forEach(resourceFile => {
                    let regex = RegExp(`href.*${resourceFile.name}" integrity="[^"]+"`, 'u');
                    const newFile = resourceInformation.files.filter(file => file.name === resourceFile.name)[0];
                    let newUrl = `href="${newFile.url}" integrity="${newFile.sriValue}"`;
                    templateFileContent = templateFileContent.replace(regex, newUrl);
                    regex = RegExp(`src.*${resourceFile.name}" integrity="[^"]+"`, 'u');
                    newUrl = `src="${newFile.url}" integrity="${newFile.sriValue}"`;
                    templateFileContent = templateFileContent.replace(regex, newUrl);
                    regex = RegExp(`resources.*${resourceFile.name}`, 'u');
                    newUrl = `resources/${resourceProperties.name}-${resourceInformation.version}/${resourceFile.name}`;
                    templateFileContent = templateFileContent.replace(regex, newUrl);
                });
                await fse.writeFile(templateFile, templateFileContent, { encoding: 'utf8' }).catch(error => {
                    console.log(error.message);
                });
            }
        }));
    }
    try {
        if (resourceProperties.version !== resourceInformation.version && resourceInformation.files.length) {
            console.log(`Resource ${resourceProperties.name} updated to version ${resourceInformation.version}`);
            resourceProperties.files.map(file => {
                file.url = file.url?.replace(resourceProperties.version, resourceInformation.version);
                file.path = file.path.replace(resourceProperties.version, resourceInformation.version);
                return file;
            });
            resourceProperties.version = resourceInformation.version;
            return true;
        }
    }
    catch (err) {
        console.log(err.message);
    }
    return false;
};
exports.updateResourcesForOneDependency = updateResourcesForOneDependency;
const deleteOldDependencies = async (resourceProperties, resourcesFolder) => {
    await Promise.all(resourceProperties.files.map(async (file) => {
        await fse.remove(`${resourcesFolder}/${file.path}/${file.name}`);
    }));
};
exports.deleteOldDependencies = deleteOldDependencies;
//# sourceMappingURL=dependency-modification-functions.js.map