"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssetsUpdater = void 0;
const bent_1 = __importDefault(require("bent"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const crypto_1 = __importDefault(require("crypto"));
const config_1 = require("./config");
const interface_1 = require("./interface");
const getJSON = (0, bent_1.default)('json');
const getBuffer = (0, bent_1.default)('buffer');
const LOG_TAG = `[${config_1.libName}]`;
class AssetsUpdater {
    constructor(context) {
        this.context = context;
    }
    /**
     * 检查本地资源文件是否过期并进行更新，每日只更新一次
     */
    updateOfflineAssetsToday() {
        return __awaiter(this, void 0, void 0, function* () {
            if (!isFileModifiedToday(this.context.getAssetsMapFilePath())) {
                console.log(`${LOG_TAG} local assets are outdated, start to download new debug assets`);
                yield this.updateOfflineAssets();
            }
            else {
                console.log(`${LOG_TAG} local assets are in the period of validity`);
            }
        });
    }
    /**
     * 更新本地资源文件
     */
    updateOfflineAssets() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.updatingTask) {
                return this.updatingTask;
            }
            this.updatingTask = this.runUpdateTask();
            try {
                yield this.updatingTask;
                this.updatingTask = undefined;
            }
            catch (error) {
                this.updatingTask = undefined;
                throw error;
            }
        });
    }
    runUpdateTask() {
        return __awaiter(this, void 0, void 0, function* () {
            // 1. 请求在线配置
            let assetsConfig;
            try {
                assetsConfig = (yield getJSON(config_1.defaultConfig.assetsQueryUrl));
            }
            catch (error) {
                throw new Error('Failed to request online config');
            }
            yield Promise.all([
                this.updateLocalFile(this.context.getAssetsMapFilePath(), assetsConfig.url_v2, assetsConfig.integrity_v2),
                this.updateLocalFile(this.context.getBoatmanFilePath(interface_1.ECompileTargetType.Mini), assetsConfig.url_boatman_mini, assetsConfig.integrity_boatman_mini),
                this.updateLocalFile(this.context.getBoatmanFilePath(interface_1.ECompileTargetType.Cube), assetsConfig.url_boatman_cube, assetsConfig.integrity_boatman_cube),
            ]);
        });
    }
    updateLocalFile(filePath, url, integrity) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!url || !integrity) {
                // 线上配置有误
                console.error(`${LOG_TAG} Empty key in config`);
                return;
            }
            // 2. 校验本地资源是否最新
            try {
                const localAssetsBuffer = yield fs_extra_1.default.readFile(filePath);
                const localAssetsHash = crypto_1.default.createHash('sha256').update(localAssetsBuffer).digest('base64');
                if (localAssetsHash === integrity) {
                    console.log(`${LOG_TAG} Local is latested`);
                    return;
                }
            }
            catch (error) {
                // 本地资源文件不存在
            }
            console.log(`${LOG_TAG} Start to update local`);
            // 3. 下载新版本资源
            let downloadBuffer;
            try {
                downloadBuffer = (yield getBuffer(url));
            }
            catch (error) {
                console.error(`${LOG_TAG} Download error ${error.message}`);
                return;
            }
            // 4. 校验下载资源文件 hash，并写入本地文件
            const downloadHash = crypto_1.default.createHash('sha256').update(downloadBuffer).digest('base64');
            if (downloadHash === integrity) {
                yield fs_extra_1.default.writeFile(filePath, downloadBuffer);
                console.log(`${LOG_TAG} Updated`);
            }
            else {
                throw new Error('Failed to verify');
            }
        });
    }
}
exports.AssetsUpdater = AssetsUpdater;
/**
 * 检查本地资源文件是否今日更新过
 * @returns {boolean} true-更新过; false-未更新
 */
function isFileModifiedToday(filePath) {
    return __awaiter(this, void 0, void 0, function* () {
        try {
            const stat = yield fs_extra_1.default.stat(filePath);
            const mtime = new Date(parseInt(`${stat.mtimeMs}`, 10));
            return new Date().toLocaleDateString() === mtime.toLocaleDateString();
        }
        catch (error) {
            return false;
        }
    });
}
