import util from '@ohos.util';
import cryptoFramework from "@ohos.security.cryptoFramework";
import buffer from "@ohos.buffer";
import { AIOCrashDeviceInfo } from './utils/AIOCrashDeviceInfo';
import BuildProfile from '../../../BuildProfile';
const LOG_START = "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***";
const SECTION_SEP = "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---";
const LOG_TYPE_EXCEPTION = "exception";
const LOG_TYPE_ANR = "anr";
const LOG_TYPE_NATIVE_CRASH = "jni";
const LOG_TYPE_JS_CRASH = "java";
export class AIOCrashStackFrameInfo {
    constructor() {
        this.index = -1;
        this.filePath = '';
        this.symbol = '';
        this.pc = '';
        this.buildId = undefined;
        this.targetModule = '';
    }
    isMatch(n4) {
        if (this.filePath.length == 0) {
            return false;
        }
        return this.filePath.indexOf(n4) != -1;
    }
    isSystemFile() {
        if (this.filePath.startsWith('/system/')) {
            return true;
        }
        for (const m4 of AIOCrashStackFrameInfo.SystemSoNames) {
            if (this.isMatch(m4)) {
                return true;
            }
        }
        return false;
    }
    static createFromInfo(j4, k4) {
        const l4 = new AIOCrashStackFrameInfo();
        l4.index = j4;
        l4.buildId = k4['buildId'];
        l4.filePath = k4['file'];
        l4.symbol = k4['symbol'];
        if (l4.buildId !== undefined) {
            l4.pc = k4['pc'];
        }
        else {
            l4.pc = l4.symbol;
        }
        return l4;
    }
    static createFromJSFrameContent(e4, f4) {
        const g4 = new AIOCrashStackFrameInfo();
        g4.index = e4;
        const h4 = /at\s+(.+?)\s+\(([^:]+)(?::(\d+))?(?::(\d+))?\)/;
        const i4 = f4.match(h4);
        if (i4) {
            g4.symbol = i4[1];
            g4.filePath = i4[2];
            g4.pc = g4.symbol;
        }
        return g4;
    }
}
AIOCrashStackFrameInfo.SystemSoNames = [
    "libc.so",
    "libdl.so",
    "libm.so",
    "libresolv.so",
    "libstdc++.so",
    "libgcc_s.so",
    "libc++.so",
    "libc++_shared.so",
    "libcrypto.so",
    "libssl.so",
    "libz.so",
    "libjnigraphics.so",
];
export class AIOCrashMatchModuleInfo {
    constructor() {
        this.firstMatchModuleName = '';
        this.firstModuleStackFrameIndex = -1;
        this.firstAppStackFrameIndex = -1;
        this.stackDeep = 0;
        this.crashTag = '';
        this.crashMsg = '';
        this.stackEncodeContent = '';
        this.stackId = '';
    }
    hasMatch() {
        return this.firstMatchModuleName.length > 0;
    }
    isMatchExactly() {
        return this.hasMatch() && this.firstModuleStackFrameIndex <= this.firstAppStackFrameIndex;
    }
    encodeStackFrames(w3) {
        this.stackEncodeContent = w3.filter(d4 => d4.targetModule.length > 0).slice(0, 30).map(c4 => `${c4.index},${c4.pc},${c4.buildId ?? ''}`).join(';');
        const x3 = cryptoFramework.createMd('MD5');
        x3.updateSync({ data: new Uint8Array(buffer.from(this.stackEncodeContent, 'utf-8').buffer) });
        this.stackId = Array.from(x3.digestSync().data).map(b4 => b4.toString(16).padStart(2, '0')).join('');
    }
    toMap() {
        return new Map([
            ['crashModule', this.firstMatchModuleName],
            ['moduleMatchExactly', this.isMatchExactly() ? '1' : '0'],
            ['appFirstIndex', this.firstAppStackFrameIndex.toString()],
            ['moduleFirstIndex', this.firstModuleStackFrameIndex.toString()],
            ['stackDeep', this.stackDeep.toString()],
            ['crashTag', this.crashTag],
            ['crashMsg', this.crashMsg],
            ['stackId', this.stackId],
            ['stack', this.stackEncodeContent],
        ]);
    }
}
export class AIOCrashLogContentBuilder {
    static createJSCrash(v3) {
        return new AIOCrashLogContentBuilder(v3, LOG_TYPE_JS_CRASH);
    }
    static createNativeCrash(u3) {
        return new AIOCrashLogContentBuilder(u3, LOG_TYPE_NATIVE_CRASH);
    }
    static createAppFreeze(t3) {
        return new AIOCrashLogContentBuilder(t3, LOG_TYPE_ANR);
    }
    constructor(r3, s3) {
        this.userId = '';
        this.content = '';
        this.appId = 'unknown';
        this.version = '';
        this.versionCode = '';
        this.subVersion = '';
        this.buildNumber = '';
        this.logType = '';
        this.processId = '';
        this.threadId = '';
        this.processName = 'unknown';
        this.threadName = '';
        this.reportUUID = '';
        this.crashTime = '';
        this.fg = 'unknown';
        this.params = '';
        this.exceptionName = '';
        this.exceptionMessage = '';
        this.signal = '';
        this.signalCode = '';
        this.stackTrace = '';
        this.stackFrames = new Array();
        this.otherThreadStackTrace = '';
        this.hiLog = '';
        this.buildImages = new Map();
        this.eventHandlerInfo = '';
        this.eventHandler3sSize = '';
        this.eventHandler6sSize = '';
        this.peerBinder = '';
        this.memory = '';
        this.firstAppFrameIndex = -1;
        this.appId = r3;
        this.logType = s3;
    }
    setUserId(q3) {
        this.userId = q3;
    }
    setSubVersion(p3) {
        this.subVersion = p3;
    }
    setBuildNumber(o3) {
        this.buildNumber = o3;
    }
    setProcessId(n3) {
        this.processId = n3;
    }
    setProcessName(m3) {
        this.processName = m3;
    }
    setThreadId(l3) {
        this.threadId = l3;
    }
    setThreadName(k3) {
        this.threadName = k3;
    }
    setReportUUID(j3) {
        this.reportUUID = j3;
    }
    setVersion(i3) {
        this.version = i3;
    }
    setVersionCode(h3) {
        this.versionCode = h3;
    }
    setCrashTime(g3) {
        this.crashTime = g3;
    }
    getCrashTime() {
        return this.crashTime;
    }
    setForeground(f3) {
        this.fg = f3;
    }
    getForeground() {
        return this.fg;
    }
    addParam(d3, e3) {
        this.params += `${d3}: ${e3}\n`;
    }
    addCustomParams(y2) {
        if (y2 && y2.size > 0) {
            y2.forEach((a3, b3) => {
                const c3 = b3.startsWith('wk_') ? b3 : `wk_${b3}`;
                this.addParam(c3, a3);
            });
        }
    }
    setParams(u2) {
        if (u2 && u2.size > 0) {
            u2.forEach((w2, x2) => {
                this.addParam(x2, w2);
            });
        }
    }
    setHiLog(t2) {
        this.hiLog = t2;
    }
    setExceptionName(s2) {
        this.exceptionName = s2;
    }
    setExceptionMessage(r2) {
        this.exceptionMessage = r2;
    }
    setSignal(q2) {
        this.signal = q2;
    }
    setSignalCode(p2) {
        this.signalCode = p2;
    }
    matchModules(l2) {
        const m2 = new AIOCrashMatchModuleInfo();
        m2.firstAppStackFrameIndex = this.firstAppFrameIndex;
        m2.stackDeep = this.stackFrames.length;
        m2.crashMsg = this.exceptionMessage;
        for (const n2 of this.stackFrames) {
            for (const o2 of l2) {
                if (n2.isMatch(o2)) {
                    n2.targetModule = o2;
                    if (m2.firstModuleStackFrameIndex == -1) {
                        m2.firstMatchModuleName = o2;
                        m2.firstModuleStackFrameIndex = n2.index;
                        m2.crashTag = n2.pc;
                    }
                    break;
                }
            }
        }
        if (m2.firstModuleStackFrameIndex == -1) {
            return undefined;
        }
        m2.encodeStackFrames(this.stackFrames);
        return m2;
    }
    setStackTrace(i2) {
        this.stackTrace = i2;
        if (this.isJSCrash()) {
            const j2 = i2.split('\n');
            this.firstAppFrameIndex = 0;
            this.stackFrames = new Array();
            for (let k2 = 0; k2 < j2.length; ++k2) {
                this.stackFrames.push(AIOCrashStackFrameInfo.createFromJSFrameContent(k2, j2[k2]));
            }
        }
    }
    stringifyFrames(e2) {
        let f2 = '';
        let g2 = 0;
        for (const h2 of e2) {
            f2 += `#${this.formatIndex(g2)} ${this.formatFrame(h2)}\n`;
            g2++;
        }
        return f2;
    }
    setStackTraceByFrames(b2) {
        this.stackTrace += this.stringifyFrames(b2);
        this.firstAppFrameIndex = this.isJSCrash() ? 0 : -1;
        this.stackFrames = new Array();
        for (let c2 = 0; c2 < b2.length; ++c2) {
            const d2 = AIOCrashStackFrameInfo.createFromInfo(c2, b2[c2]);
            if (this.firstAppFrameIndex === -1 && (this.isNativeCrash() || this.isAppFreeze()) && !d2.isSystemFile()) {
                this.firstAppFrameIndex = d2.index;
            }
            this.stackFrames.push(d2);
        }
    }
    addOtherThreads(x1) {
        if (x1 === undefined || x1.length <= 0) {
            return;
        }
        for (const y1 of x1) {
            const z1 = y1['tid'];
            const a2 = y1['frames'];
            if (this.processId == z1 && this.isAppFreeze()) {
                this.stackTrace += `"${y1['thread_name']}" tid=${z1}\n`;
                this.stackTrace += `pid: ${this.processId}, tid: ${z1}\n`;
                this.setStackTraceByFrames(a2);
                continue;
            }
            if (this.otherThreadStackTrace.length > 0) {
                this.otherThreadStackTrace += SECTION_SEP + '\n';
            }
            this.otherThreadStackTrace += `Thread Name: '${y1['thread_name']}'\n`;
            this.otherThreadStackTrace += `pid: ${this.processId}, tid: ${z1}\n`;
            this.otherThreadStackTrace += this.stringifyFrames(a2);
        }
    }
    setEventHandlerInfo(w1) {
        this.eventHandlerInfo = w1.join('\n');
    }
    setEventHandler3sSize(v1) {
        this.eventHandler3sSize = v1;
    }
    setEventHandler6sSize(u1) {
        this.eventHandler6sSize = u1;
    }
    setPeerBinder(t1) {
        this.peerBinder = t1.join('\n');
    }
    setMemory(s1) {
        this.memory += `MemTotal: ${s1['sys_total_mem']} KB\n`;
        this.memory += `MemFree: ${s1['sys_free_mem']} KB\n`;
        this.memory += `MemAvailable: ${s1['sys_avail_mem']} KB\n`;
        this.memory += `RSS: ${s1['rss']} KB\n`;
        this.memory += `VSS: ${s1['vss']} KB\n`;
        this.memory += `PSS: ${s1['pss']} KB\n`;
    }
    getLogType() {
        return this.logType;
    }
    isJSCrash() {
        return this.logType == LOG_TYPE_JS_CRASH;
    }
    isNativeCrash() {
        return this.logType == LOG_TYPE_NATIVE_CRASH;
    }
    isAppFreeze() {
        return this.logType == LOG_TYPE_ANR;
    }
    formatIndex(r1) {
        return r1 < 10 ? '0' + r1 : r1.toString();
    }
    formatFrame(j1) {
        let k1 = '';
        const l1 = j1['buildId'];
        const m1 = j1['file'];
        if (l1 !== undefined && !this.buildImages.has(l1)) {
            this.buildImages.set(l1, m1);
        }
        let n1 = j1['symbol'];
        if (l1 !== undefined) {
            const q1 = j1['offset'];
            if (n1.length > 0) {
                n1 = `(${n1}+${q1})`;
            }
            k1 += `pc ${j1['pc']} ${m1} ${n1}`;
        }
        else {
            const o1 = j1['line'];
            const p1 = j1['column'];
            k1 += `at ${n1} (${m1}:${o1}:${p1})`;
        }
        return k1;
    }
    appendLineContent(i1) {
        this.content += `${i1}\n`;
    }
    start() {
        this.appendLineContent(LOG_START);
    }
    addSectionSep() {
        this.appendLineContent(SECTION_SEP);
    }
    buildBasicInfoSection(d1, e1, f1, g1, h1) {
        this.appendLineContent(`Basic Information: 'pid: ${e1}/tid: ${f1}/time: ${g1}'`);
        this.appendLineContent(`Cpu Information: 'abi: ${AIOCrashDeviceInfo.getABIList()}'`);
        this.appendLineContent(`Mobile Information: 'model: ${AIOCrashDeviceInfo.getModel()}/version: ${AIOCrashDeviceInfo.getDistributionOSVersion()}/sdk: ${AIOCrashDeviceInfo.getOSSDKApiVersion()}/fr: harmony'`);
        this.appendLineContent(`Build fingerprint: '${AIOCrashDeviceInfo.getBrand()}/${AIOCrashDeviceInfo.getModel()}/null/null/0.0.0.000000:null/release-keys'`);
        this.appendLineContent(`Runtime Information: 'start: ${g1}/maxheap: 0000/primaryabi: null/ground: ${h1}'`);
        this.appendLineContent(`Application Information: 'version: ${this.version}/subversion: ${this.subVersion}/buildseq:  ${this.buildNumber}/versioncode: ${this.versionCode}'`);
        this.appendLineContent(`CrashSDK Information: 'version: ${BuildProfile.HAR_VERSION}/nativeseq: ${BuildProfile.HAR_COMMIT_ID}/javaseq: ${BuildProfile.HAR_BUILD_ID}/target: ${BuildProfile.BUILD_MODE_NAME}'`);
        this.appendLineContent(`UUID: ${this.userId}`);
        this.appendLineContent(`Report Name: ${this.buildReportName()}`);
        this.appendLineContent(`Log Type: ${d1}`);
    }
    buildParamsSection() {
        this.appendLineContent(this.params);
    }
    buildLogcatSection() {
        this.appendLineContent('logcat:');
        this.appendLineContent(this.hiLog);
    }
    buildJSExceptionStackSection() {
        this.appendLineContent(`ProcessName: '${this.processName}'`);
        this.appendLineContent('Back traces starts.');
        this.appendLineContent(`${this.exceptionName}: ${this.exceptionMessage}`);
        this.appendLineContent(this.stackTrace);
        this.appendLineContent('Back traces ends.');
    }
    buildNativeCrashStackSection() {
        this.appendLineContent(`Process Name: '${this.processName}'`);
        this.appendLineContent(`Thread Name: '${this.threadName}'`);
        this.appendLineContent(`pid: ${this.processId}, tid: ${this.threadId}, >>> ${this.processName} <<<`);
        this.appendLineContent(`signal: ${this.signal}, code: ${this.signalCode}`);
        this.appendLineContent(this.stackTrace);
    }
    buildOtherThreadSection() {
        this.appendLineContent(this.otherThreadStackTrace);
    }
    buildImagesSection() {
        this.appendLineContent('solib build id:');
        this.buildImages.forEach((b1, c1) => {
            this.appendLineContent(`${b1}: ${c1}`);
        });
    }
    buildANRReasonSection() {
        this.appendLineContent(`Process Name: '${this.processName}'`);
        let z = `${this.exceptionName}`;
        if (this.exceptionMessage.length > 0) {
            z += ` (${this.exceptionMessage})`;
        }
        this.appendLineContent(`Reason: '${z}`);
        this.appendLineContent('');
        this.appendLineContent('event handler info:');
        this.appendLineContent(`event_handler_size_3s: ${this.eventHandler3sSize}`);
        this.appendLineContent(`event_handler_size_6s: ${this.eventHandler6sSize}`);
        this.appendLineContent(`\nLow priority event queue information:\n${this.eventHandlerInfo}`);
        this.appendLineContent('');
        this.appendLineContent(`peer binder:\n${this.peerBinder}`);
    }
    buildANRTraceSection() {
        this.appendLineContent(`anr traces:`);
        this.appendLineContent(this.stackTrace);
    }
    buildMemoryInfo() {
        this.appendLineContent('meminfo:');
        this.appendLineContent(this.memory);
    }
    buildReportName() {
        if (this.reportUUID.length <= 0) {
            this.reportUUID = util.generateRandomUUID();
        }
        let y = AIOCrashDeviceInfo.getModel();
        y = y.replace(/[^0-9a-zA-Z-.]/g, '-');
        return `${this.appId}_${this.version}_${this.buildNumber}_${y}_${AIOCrashDeviceInfo.getOSSDKApiVersion()}_${this.userId}_${this.crashTime}_${this.fg}_${this.logType}.log`;
    }
    buildLog() {
        if (this.content.length <= 0) {
            this.start();
            this.buildBasicInfoSection(this.logType, this.processId, this.threadId, this.crashTime, this.fg);
            this.addSectionSep();
            this.buildParamsSection();
            this.addSectionSep();
            if (this.isJSCrash()) {
                this.buildJSExceptionStackSection();
            }
            else if (this.isNativeCrash()) {
                this.buildNativeCrashStackSection();
                this.addSectionSep();
                this.buildOtherThreadSection();
                this.addSectionSep();
                this.buildImagesSection();
            }
            else if (this.isAppFreeze()) {
                this.buildANRReasonSection();
                this.addSectionSep();
                this.buildANRTraceSection();
                this.addSectionSep();
                this.buildOtherThreadSection();
                this.addSectionSep();
                this.buildMemoryInfo();
                this.addSectionSep();
                this.buildImagesSection();
            }
            this.addSectionSep();
            if (this.hiLog && this.hiLog.length > 0) {
                this.buildLogcatSection();
                this.addSectionSep();
            }
        }
        return this.content;
    }
}
