"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalysisTemplateManager = void 0;
const fourQuadrantAnalysis_1 = require("./fourQuadrantAnalysis");
const cpuCoreAnalysis_1 = require("./cpuCoreAnalysis");
const frameStatsAnalysis_1 = require("./frameStatsAnalysis");
class AnalysisTemplateManager {
    constructor(traceProcessor) {
        this.traceProcessor = traceProcessor;
        this.fourQuadrantAnalyzer = new fourQuadrantAnalysis_1.FourQuadrantAnalyzer(traceProcessor);
        this.cpuCoreAnalyzer = new cpuCoreAnalysis_1.CpuCoreAnalyzer(traceProcessor);
    }
    /**
     * 根据用户问题自动选择并执行分析模板
     */
    async analyzeWithAutoTemplate(context) {
        const templateName = this.selectTemplate(context.question);
        if (templateName === 'custom') {
            return null; // 需要自定义 SQL
        }
        try {
            const result = await this.executeTemplate(templateName, context);
            return {
                templateName,
                data: result,
                summary: this.generateSummary(templateName, result),
            };
        }
        catch (error) {
            console.error(`Failed to execute template ${templateName}:`, error);
            return null;
        }
    }
    /**
     * 根据问题选择合适的模板
     */
    selectTemplate(question) {
        const questionLower = question.toLowerCase();
        // 四大象限分析
        if (questionLower.includes('四大象限') ||
            questionLower.includes('binder') ||
            questionLower.includes('lock') ||
            questionLower.includes('io') ||
            (questionLower.includes('耗时') && questionLower.includes('分布')) ||
            questionLower.includes('时间占比')) {
            return 'four_quadrant';
        }
        // CPU 核心分布
        if (questionLower.includes('cpu') ||
            questionLower.includes('核心') ||
            questionLower.includes('大核') ||
            questionLower.includes('小核') ||
            questionLower.includes('big core') ||
            questionLower.includes('little core')) {
            return 'cpu_core_distribution';
        }
        // 帧率统计
        if (questionLower.includes('fps') ||
            questionLower.includes('帧率') ||
            questionLower.includes('掉帧') ||
            questionLower.includes('jank') ||
            questionLower.includes('卡顿') ||
            questionLower.includes('流畅') ||
            questionLower.includes('frame')) {
            return 'frame_stats';
        }
        // 默认返回自定义
        return 'custom';
    }
    /**
     * 执行指定的分析模板
     */
    async executeTemplate(templateName, context) {
        switch (templateName) {
            case 'four_quadrant':
                return await this.executeFourQuadrant(context);
            case 'cpu_core_distribution':
                return await this.executeCpuCoreDistribution(context);
            case 'frame_stats':
                return await this.executeFrameStats(context);
            default:
                throw new Error(`Unknown template: ${templateName}`);
        }
    }
    async executeFourQuadrant(context) {
        const params = await this.extractFourQuadrantParams(context);
        return await this.fourQuadrantAnalyzer.analyze(context.traceId, params.startTs, params.endTs, params.threadId);
    }
    async executeCpuCoreDistribution(context) {
        // 需要找到主线程的 utid
        // 简单实现：查找第一个进程的主线程
        const mainThreadUtid = await this.findMainThread(context.traceId);
        if (!mainThreadUtid) {
            throw new Error('Could not find main thread');
        }
        return await this.cpuCoreAnalyzer.analyze(context.traceId, mainThreadUtid);
    }
    async executeFrameStats(context) {
        const frameStatsAnalyzer = new frameStatsAnalysis_1.FrameStatsAnalyzer(this.traceProcessor, {
            detectedVsyncPeriodNs: context.metadata?.detectedVsyncPeriodNs,
            deviceRefreshRate: context.metadata?.deviceRefreshRate,
        });
        // 尝试使用 actual_frame_timeline_slice
        try {
            return await frameStatsAnalyzer.analyze(context.traceId);
        }
        catch (error) {
            // 降级到基于 slice 的分析
            console.warn('Frame timeline not available, falling back to slice-based analysis');
            // 需要找到进程名
            const processName = await this.findMainProcess(context.traceId);
            return await frameStatsAnalyzer.analyzeFromSlices(context.traceId, processName || 'unknown');
        }
    }
    /**
     * 查找主线程 utid
     */
    async findMainThread(traceId) {
        try {
            const query = `
        SELECT utid
        FROM thread
        WHERE name = 'main' OR tid = pid
        LIMIT 1
      `;
            const result = await this.traceProcessor.query(traceId, query);
            if (result && result.rows && result.rows.length > 0) {
                return result.rows[0][0];
            }
        }
        catch (error) {
            console.error('Failed to find main thread:', error);
        }
        return null;
    }
    /**
     * 查找主进程名称
     */
    async findMainProcess(traceId) {
        try {
            const query = `
        SELECT name
        FROM process
        WHERE name IS NOT NULL
        ORDER BY upid
        LIMIT 1
      `;
            const result = await this.traceProcessor.query(traceId, query);
            if (result && result.rows && result.rows.length > 0) {
                return result.rows[0][0];
            }
        }
        catch (error) {
            console.error('Failed to find main process:', error);
        }
        return null;
    }
    /**
     * 从问题中提取四大象限分析参数
     */
    async extractFourQuadrantParams(context) {
        const { startTs, endTs } = this.parseTimeRange(context.question);
        const threadId = await this.resolveThreadId(context.traceId, context.question);
        return { startTs, endTs, threadId };
    }
    parseTimeRange(question) {
        const unitMatches = Array.from(question.matchAll(/(\d+(?:\.\d+)?)\s*(ns|us|µs|ms|s|纳秒|微秒|毫秒|秒)/gi));
        const toNs = (value, unit) => {
            const normalized = unit.toLowerCase();
            switch (normalized) {
                case 'ns':
                case '纳秒':
                    return value;
                case 'us':
                case 'µs':
                case '微秒':
                    return value * 1e3;
                case 'ms':
                case '毫秒':
                    return value * 1e6;
                case 's':
                case '秒':
                    return value * 1e9;
                default:
                    return value;
            }
        };
        if (unitMatches.length >= 2) {
            const start = toNs(parseFloat(unitMatches[0][1]), unitMatches[0][2]);
            const end = toNs(parseFloat(unitMatches[1][1]), unitMatches[1][2]);
            return start <= end ? { startTs: start, endTs: end } : { startTs: end, endTs: start };
        }
        const startMatch = question.match(/start(?:_ts)?\s*[:=]\s*(\d+)/i);
        const endMatch = question.match(/end(?:_ts)?\s*[:=]\s*(\d+)/i);
        if (startMatch && endMatch) {
            const start = Number.parseInt(startMatch[1], 10);
            const end = Number.parseInt(endMatch[1], 10);
            return start <= end ? { startTs: start, endTs: end } : { startTs: end, endTs: start };
        }
        const numberMatches = question.match(/\d+(?:\.\d+)?/g);
        if (numberMatches && numberMatches.length >= 2) {
            const hasMs = /ms|毫秒/i.test(question);
            const hasS = /(^|[^m])s|秒/i.test(question);
            const unit = hasMs ? 'ms' : (hasS ? 's' : '');
            if (unit) {
                const start = toNs(parseFloat(numberMatches[0]), unit);
                const end = toNs(parseFloat(numberMatches[1]), unit);
                return start <= end ? { startTs: start, endTs: end } : { startTs: end, endTs: start };
            }
        }
        return {};
    }
    async resolveThreadId(traceId, question) {
        const utidMatch = question.match(/utid\s*[:=]\s*(\d+)/i);
        if (utidMatch) {
            return Number.parseInt(utidMatch[1], 10);
        }
        const tidMatch = question.match(/tid\s*[:=]\s*(\d+)/i);
        if (tidMatch) {
            const tid = Number.parseInt(tidMatch[1], 10);
            const utid = await this.findUtidByTid(traceId, tid);
            if (utid)
                return utid;
        }
        if (/主线程|main thread|ui thread/i.test(question)) {
            const mainThread = await this.findMainThread(traceId);
            if (mainThread)
                return mainThread;
        }
        return undefined;
    }
    async findUtidByTid(traceId, tid) {
        try {
            const query = `
        SELECT utid
        FROM thread
        WHERE tid = ${tid}
        LIMIT 1
      `;
            const result = await this.traceProcessor.query(traceId, query);
            if (result && result.rows && result.rows.length > 0) {
                return result.rows[0][0];
            }
        }
        catch (error) {
            console.error('Failed to resolve utid from tid:', error);
        }
        return null;
    }
    /**
     * 生成分析摘要
     */
    generateSummary(templateName, data) {
        switch (templateName) {
            case 'four_quadrant':
                return this.summarizeFourQuadrant(data);
            case 'cpu_core_distribution':
                return this.summarizeCpuCoreDistribution(data);
            case 'frame_stats':
                return this.summarizeFrameStats(data);
            default:
                return 'Analysis completed';
        }
    }
    summarizeFourQuadrant(result) {
        const { summary } = result;
        const sorted = [...summary.breakdown].sort((a, b) => b.durationMs - a.durationMs);
        const top = sorted[0];
        return `总时长 ${summary.totalMs.toFixed(2)}ms，其中 ${this.getCategoryLabel(top.category)} 占比最高（${top.percentage.toFixed(1)}%，${top.durationMs.toFixed(2)}ms）`;
    }
    summarizeCpuCoreDistribution(result) {
        const { summary } = result;
        return `大核使用 ${summary.bigCorePercentage.toFixed(1)}%（${summary.bigCoreMs.toFixed(2)}ms），小核使用 ${summary.littleCorePercentage.toFixed(1)}%（${summary.littleCoreMs.toFixed(2)}ms）`;
    }
    summarizeFrameStats(result) {
        const { summary, percentiles } = result;
        return `平均帧率 ${summary.avgFps.toFixed(1)} FPS，掉帧率 ${summary.jankPercentage.toFixed(1)}%（${summary.jankCount}/${summary.totalFrames} 帧），P95延迟 ${percentiles.p95Ms.toFixed(2)}ms`;
    }
    getCategoryLabel(category) {
        const labels = {
            binder: 'Binder调用',
            lock: 'Lock等待',
            io: 'IO操作',
            computation: 'CPU计算',
        };
        return labels[category] || category;
    }
}
exports.AnalysisTemplateManager = AnalysisTemplateManager;
//# sourceMappingURL=templateManager.js.map