"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.BuilderDebugClient = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const interface_1 = require("./interface");
const updater_1 = require("./updater");
const config_1 = require("./config");
const compose_1 = require("./compose");
const context_1 = require("./context");
class BuilderDebugClient {
    constructor(options) {
        this.context = new context_1.BuilderDebugContext(Object.assign(Object.assign({}, config_1.defaultConfig), options));
    }
    updateOfflineAssets(options) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.assetsUpdater) {
                this.assetsUpdater = new updater_1.AssetsUpdater(this.context);
            }
            if (options.cacheToday) {
                yield this.assetsUpdater.updateOfflineAssetsToday();
            }
            else {
                yield this.assetsUpdater.updateOfflineAssets();
            }
        });
    }
    generateInjectCode(options) {
        return __awaiter(this, void 0, void 0, function* () {
            options = getInjectCodeOptions(options);
            const assetsMap = yield this.readAssetsMap();
            return (0, compose_1.composeAssetsByCompileMode)(assetsMap, options);
        });
    }
    /**
     * generateInjectCode 同步方法
     */
    generateInjectCodeSync(options) {
        options = getInjectCodeOptions(options);
        const assetsMap = this.readAssetsMapSync();
        return (0, compose_1.composeAssetsByCompileMode)(assetsMap, options);
    }
    readAssetsMapSync() {
        let localJSON = fs_extra_1.default.readJSONSync(this.context.getAssetsMapFilePath(), { throws: false });
        if (!localJSON) {
            console.log(`[${config_1.libName}] offline assets_map file was damaged, fallback to readonly file`);
            // 避免文件损坏，readonly/assets_map 做兜底
            localJSON = fs_extra_1.default.readJSONSync(this.context.getReadonlyAssetsMapFilePath());
        }
        return localJSON;
    }
    readAssetsMap() {
        return __awaiter(this, void 0, void 0, function* () {
            let localJSON;
            try {
                localJSON = yield fs_extra_1.default.readJSON(this.context.getAssetsMapFilePath(), { throws: false });
            }
            catch (error) {
                // throws if file is not found
            }
            if (!localJSON) {
                console.log(`[${config_1.libName}] offline assets_map file was damaged, fallback to readonly file`);
                // 避免文件损坏，readonly/assets_map 做兜底
                localJSON = yield fs_extra_1.default.readJSON(this.context.getReadonlyAssetsMapFilePath());
            }
            return localJSON;
        });
    }
    /**
     * 生成构建器消费的 InjectCode JSON 文件，并返回路径
     */
    generateInjectCodePath(options) {
        return __awaiter(this, void 0, void 0, function* () {
            const injectCode = yield this.generateInjectCode(options);
            yield fs_extra_1.default.writeJSON(config_1.defaultConfig.injectCodeTempPath, injectCode);
            return config_1.defaultConfig.injectCodeTempPath;
        });
    }
    /**
     * generateInjectCodePath 同步方法
     */
    generateInjectCodePathSync(options) {
        const injectCode = this.generateInjectCodeSync(options);
        fs_extra_1.default.writeJSONSync(config_1.defaultConfig.injectCodeTempPath, injectCode);
        return config_1.defaultConfig.injectCodeTempPath;
    }
    /**
     * 获取本地 boatman 文件资源路径
     */
    getBoatmanBundlePath(options) {
        return __awaiter(this, void 0, void 0, function* () {
            const opt = getGetBoatmanBundleOptions(options);
            // 若文件不存在降级到 readonly 备份
            try {
                const offlineFile = this.context.getBoatmanFilePath(opt.target);
                yield fs_extra_1.default.access(offlineFile, fs_extra_1.default.constants.R_OK);
                return offlineFile;
            }
            catch (error) {
                return this.context.getReadonlyBoatmanFilePath(opt.target);
            }
        });
    }
    /**
     * getBoatmanBundlePath 同步方法
     */
    getBoatmanBundlePathSync(options) {
        const opt = getGetBoatmanBundleOptions(options);
        try {
            const offlineFile = this.context.getBoatmanFilePath(opt.target);
            fs_extra_1.default.accessSync(offlineFile, fs_extra_1.default.constants.R_OK);
            return offlineFile;
        }
        catch (error) {
            return this.context.getReadonlyBoatmanFilePath(opt.target);
        }
    }
}
exports.BuilderDebugClient = BuilderDebugClient;
function getGetBoatmanBundleOptions(options) {
    const result = {
        target: interface_1.ECompileTargetType.Mini,
    };
    if (options.target && Object.keys(interface_1.ECompileTargetType).indexOf(options.target) > -1) {
        result.target = options.target;
    }
    return result;
}
function getInjectCodeOptions(options) {
    const opt = Object.assign({}, options);
    if (!opt.mode || Object.keys(interface_1.ECompileModeType).indexOf(opt.mode) === -1) {
        throw new Error(`[${config_1.libName}] invalid 'mode' option: ${opt.mode}`);
    }
    if (!opt.target || Object.keys(interface_1.ECompileTargetType).indexOf(opt.target) === -1) {
        opt.target = interface_1.ECompileTargetType.Mini;
    }
    return options;
}
