"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.resolveJsCodeCacheFilename = exports.compileEncrypt = exports.isUTSModules = exports.isEncrypt = void 0;
const path_1 = __importStar(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const shared_1 = require("./shared");
const kotlin_1 = require("./kotlin");
const utils_1 = require("./utils");
const manifest_1 = require("./manifest");
const fast_glob_1 = require("fast-glob");
const dex_1 = require("./manifest/dex");
const kotlin_2 = require("./stacktrace/kotlin");
function isEncrypt(pluginDir) {
    return fs_extra_1.default.existsSync(path_1.default.resolve(pluginDir, 'encrypt'));
}
exports.isEncrypt = isEncrypt;
function isUTSModules(pluginDir) {
    return fs_extra_1.default.existsSync(path_1.default.resolve(pluginDir, 'utssdk'));
}
exports.isUTSModules = isUTSModules;
function createRollupCommonjsCode(_pluginDir, pluginRelativeDir) {
    // const name = makeLegalIdentifier(pluginRelativeDir)
    return `
export default uni.requireUTSPlugin('${(0, shared_1.normalizePath)(pluginRelativeDir)}')
`;
}
function createWebpackCommonjsCode(pluginRelativeDir) {
    return `
module.exports = uni.requireUTSPlugin('${(0, shared_1.normalizePath)(pluginRelativeDir)}')
`;
}
async function compileEncrypt(pluginDir, isX = false) {
    if (isX && !fs_extra_1.default.existsSync(path_1.default.resolve(pluginDir, 'utssdk'))) {
        return compileEncryptByUniHelpers(pluginDir);
    }
    const inputDir = process.env.UNI_INPUT_DIR;
    const outputDir = process.env.UNI_OUTPUT_DIR;
    const utsPlatform = process.env.UNI_UTS_PLATFORM;
    const isRollup = !!process.env.UNI_UTS_USING_ROLLUP;
    const pluginRelativeDir = (0, path_1.relative)(inputDir, pluginDir);
    const outputPluginDir = (0, shared_1.normalizePath)((0, path_1.join)(outputDir, pluginRelativeDir));
    const isNative = isX && utsPlatform === 'app-android';
    let code = isNative
        ? 'export default {}'
        : isRollup
            ? createRollupCommonjsCode(pluginDir, pluginRelativeDir)
            : createWebpackCommonjsCode(pluginRelativeDir);
    if (process.env.NODE_ENV !== 'development') {
        // 生成wgt，无需复制加密插件目录
        const needCopy = !(process.env.UNI_APP_PRODUCTION_TYPE === 'WGT');
        if (needCopy) {
            // 复制插件目录
            fs_extra_1.default.copySync(pluginDir, (0, path_1.join)(outputDir, pluginRelativeDir));
        }
        return {
            dir: outputPluginDir,
            code,
            deps: [],
            encrypt: true,
            inject_apis: [],
            scoped_slots: [],
            custom_elements: {},
            meta: { commonjs: { isCommonJS: true } },
        };
    }
    const cacheDir = process.env.HX_DEPENDENCIES_DIR;
    if (!isNative) {
        // 读取缓存目录的 js code
        const indexJsPath = resolveJsCodeCacheFilename(utsPlatform, cacheDir, pluginRelativeDir);
        if (fs_extra_1.default.existsSync(indexJsPath)) {
            code = fs_extra_1.default.readFileSync(indexJsPath, 'utf-8') + code;
        }
        else {
            console.error(`uts插件[${path_1.default.basename(pluginDir)}]不存在，请重新打包自定义基座`);
        }
    }
    else {
        const jarPath = resolveJarCacheFilename(cacheDir, pluginRelativeDir);
        if (!fs_extra_1.default.existsSync(jarPath)) {
            console.error(`uts插件[${path_1.default.basename(pluginDir)}]不存在，请重新打包自定义基座`);
        }
    }
    return {
        dir: outputPluginDir,
        code,
        deps: [],
        encrypt: true,
        inject_apis: [],
        scoped_slots: [],
        custom_elements: {},
        meta: { commonjs: { isCommonJS: true } },
    };
}
exports.compileEncrypt = compileEncrypt;
function resolveJsCodeCacheFilename(platform, cacheDir, pluginRelativeDir) {
    return (0, path_1.join)(cacheDir, platform, 'uts', pluginRelativeDir, 'index.js');
}
exports.resolveJsCodeCacheFilename = resolveJsCodeCacheFilename;
function resolveJarCacheFilename(cacheDir, pluginRelativeDir) {
    return (0, path_1.join)(cacheDir, 'app-android', 'uts', pluginRelativeDir, 'index.jar');
}
async function compileEncryptByUniHelpers(pluginDir) {
    // 目前仅Android会进来
    const cacheDir = process.env.HX_DEPENDENCIES_DIR || '';
    const inputDir = process.env.UNI_INPUT_DIR;
    const outputDir = process.env.UNI_OUTPUT_DIR;
    const pluginRelativeDir = (0, path_1.relative)(inputDir, pluginDir);
    const outputPluginDir = (0, shared_1.normalizePath)((0, path_1.join)(outputDir, pluginRelativeDir));
    // 读取缓存文件
    const cachePluginDir = path_1.default.resolve(process.env.UNI_MODULES_ENCRYPT_CACHE_DIR, pluginRelativeDir);
    const cacheFile = (0, dex_1.resolveDexCacheFile)(pluginRelativeDir, cacheDir);
    if (process.env.NODE_ENV === 'development' && cacheFile) {
        // 已有缓存
        (0, manifest_1.restoreDex)(pluginRelativeDir, cacheDir, outputDir, true);
        const assets = path_1.default.resolve(cachePluginDir, 'assets');
        if (fs_extra_1.default.existsSync(assets)) {
            fs_extra_1.default.copySync(assets, path_1.default.resolve(outputDir, pluginRelativeDir, 'assets'));
        }
        return {
            dir: outputPluginDir,
            code: 'export default {}',
            deps: [],
            encrypt: true,
            inject_apis: [],
            scoped_slots: [],
            custom_elements: {},
        };
    }
    const pkg = require(path_1.default.resolve(cachePluginDir, 'package.json'));
    if (process.env.NODE_ENV !== 'development') {
        // 生成wgt，无需复制加密插件目录
        const needCopy = !(process.env.UNI_APP_PRODUCTION_TYPE === 'WGT');
        if (needCopy) {
            // 复制非kt资源
            fs_extra_1.default.copySync(cachePluginDir, (0, path_1.join)(outputDir, pluginRelativeDir), {
                filter(src) {
                    return !src.endsWith('app-android');
                },
            });
            // copy kt to src
            fs_extra_1.default.copySync(path_1.default.resolve(cachePluginDir, 'utssdk', 'app-android'), (0, path_1.join)(outputDir, pluginRelativeDir, 'utssdk', 'app-android', 'src'), {
                filter(src) {
                    if (fs_extra_1.default.statSync(src).isDirectory())
                        return true;
                    return src.endsWith('.kt');
                },
                overwrite: false,
            });
            // 需要把 kt 文件放到 app-android/src 下
        }
        const artifacts = pkg.uni_modules?.artifacts;
        const inject_apis = artifacts?.apis || [];
        const scoped_slots = artifacts?.scopedSlots || [];
        const custom_elements = artifacts?.customElements || {};
        (0, utils_1.addPluginInjectApis)(inject_apis);
        (0, utils_1.addPluginInjectComponents)(artifacts?.components || []);
        (0, utils_1.addPluginInjectCustomElements)(custom_elements);
        return {
            dir: outputPluginDir,
            code: 'export default {}',
            deps: [],
            encrypt: true,
            inject_apis,
            scoped_slots,
            custom_elements,
        };
    }
    // development
    if (process.env.UNI_HBUILDERX_PLUGINS) {
        const { DUM } = (0, utils_1.requireUniHelpers)();
        const ktFiles = (0, fast_glob_1.sync)('**/*.kt', {
            absolute: false,
            cwd: cachePluginDir,
        }).reduce((files, file) => {
            files[path_1.default.resolve(cachePluginDir, file)] = path_1.default.resolve(process.env.UNI_OUTPUT_DIR, pluginRelativeDir, file);
            return files;
        }, {});
        const errMsg = await DUM(path_1.default.basename(pluginRelativeDir), ktFiles);
        if (errMsg) {
            console.error(errMsg);
            process.exit(0);
        }
        const jarFile = (0, kotlin_1.resolveJarPath)('app-android', cacheDir, pluginRelativeDir, 'index.kt');
        const waiting = { done: undefined };
        const kotlinFiles = Object.values(ktFiles);
        const uniModules = require(path_1.default.resolve(pluginDir, 'package.json')).uni_modules
            ?.dependencies || [];
        const depJars = uniModules.length
            ? (0, kotlin_1.getUniModulesCacheJars)(cacheDir, uniModules) // 依赖的jar
            : [];
        const compilerServer = (0, utils_1.getCompilerServer)('uniapp-runextension');
        if (!compilerServer) {
            throw new Error(`项目使用了uts插件，正在安装 uts Android 运行扩展...`);
        }
        const { code, msg } = await (0, kotlin_1.compileAndroidDex)(true, compilerServer, kotlinFiles, jarFile, '', depJars, (0, kotlin_1.createStderrListener)(outputDir, (0, shared_1.resolveSourceMapPath)(), waiting, (m) => {
            if (m.file) {
                const file = (0, shared_1.normalizePath)(m.file);
                if (file.startsWith(outputPluginDir)) {
                    // 过滤部分插件的非错误信息
                    if (m.type !== 'error') {
                        return '';
                    }
                    else {
                        // 移除完整路径
                        m.file = pluginDir;
                    }
                }
            }
            return (0, kotlin_2.hbuilderFormatter)(m);
        }));
        // 等待 stderrListener 执行完毕
        if (waiting.done) {
            await waiting.done;
        }
        try {
            kotlinFiles.forEach((file) => {
                fs_extra_1.default.removeSync(file);
            });
        }
        catch (e) { }
        if (!code) {
            const dexFile = (0, kotlin_1.resolveDexFile)(jarFile);
            if (fs_extra_1.default.existsSync(dexFile)) {
                (0, manifest_1.restoreDex)(pluginRelativeDir, cacheDir, outputDir, true);
            }
        }
        else if (msg) {
            console.error(msg);
        }
        const assets = path_1.default.resolve(cachePluginDir, 'assets');
        if (fs_extra_1.default.existsSync(assets)) {
            fs_extra_1.default.copySync(assets, path_1.default.resolve(outputDir, pluginRelativeDir, 'assets'));
        }
    }
    return {
        dir: outputPluginDir,
        code: 'export default {}',
        deps: [],
        encrypt: true,
        inject_apis: [],
        scoped_slots: [],
        custom_elements: {},
    };
}
