"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiskMonitor = void 0;
const base_monitor_1 = require("../core/base-monitor");
const types_1 = require("../types");
/**
 * 磁盘监控器
 *
 * 提供磁盘相关的监控功能，包括空间使用、I/O统计、挂载点等
 */
class DiskMonitor extends base_monitor_1.BaseMonitor {
    constructor(adapter, config = {}, cache) {
        super(adapter, config, cache);
        this.diskConfig = { ...this.getDefaultConfig(), ...config };
    }
    /**
     * 获取所有磁盘信息
     */
    async info() {
        const cacheKey = 'disk-info';
        return this.executeWithCache(cacheKey, async () => {
            this.validatePlatformSupport('disk.info');
            const rawData = await this.adapter.getDiskInfo();
            return this.transformDiskInfo(rawData);
        }, this.diskConfig.cacheTTL || 30000 // 磁盘信息缓存 30 秒
        );
    }
    /**
     * 获取指定磁盘的信息
     */
    async infoByDevice(device) {
        const allDisksResult = await this.info();
        if (!allDisksResult.success || !allDisksResult.data) {
            return allDisksResult;
        }
        const diskInfo = allDisksResult.data.find(disk => disk.device === device || disk.mountpoint === device);
        return this.createSuccessResult(diskInfo || null);
    }
    /**
     * 获取磁盘使用情况
     */
    async usage() {
        const cacheKey = 'disk-usage';
        return this.executeWithCache(cacheKey, async () => {
            this.validatePlatformSupport('disk.usage');
            const rawData = await this.adapter.getDiskUsage();
            return this.transformDiskUsage(rawData);
        }, this.diskConfig.cacheTTL || 10000);
    }
    /**
     * 获取总体磁盘使用率（百分比）
     */
    async overallUsage() {
        const usageResult = await this.usage();
        if (!usageResult.success || !usageResult.data) {
            return usageResult;
        }
        // 计算所有磁盘的加权平均使用率
        let totalBytes = 0;
        let usedBytes = 0;
        for (const disk of usageResult.data) {
            if (this.diskConfig.excludeTypes &&
                this.diskConfig.excludeTypes.includes(disk.filesystem)) {
                continue;
            }
            totalBytes += disk.total.toBytes();
            usedBytes += disk.used.toBytes();
        }
        const usagePercentage = totalBytes > 0 ? (usedBytes / totalBytes) * 100 : 0;
        return this.createSuccessResult(Math.round(usagePercentage * 100) / 100);
    }
    /**
     * 获取指定挂载点的使用情况
     */
    async usageByMountPoint(mountPoint) {
        const allUsageResult = await this.usage();
        if (!allUsageResult.success || !allUsageResult.data) {
            return allUsageResult;
        }
        const usage = allUsageResult.data.find(disk => disk.mountpoint === mountPoint);
        return this.createSuccessResult(usage || null);
    }
    /**
     * 获取磁盘 I/O 统计
     */
    async stats() {
        if (!this.diskConfig.includeStats) {
            return this.createErrorResult(this.createUnsupportedError('disk.stats (disabled in config)'));
        }
        const cacheKey = 'disk-stats';
        return this.executeWithCache(cacheKey, async () => {
            this.validatePlatformSupport('disk.stats');
            const rawData = await this.adapter.getDiskStats();
            return this.transformDiskStats(rawData);
        }, this.diskConfig.cacheTTL || 5000);
    }
    /**
     * 获取挂载点信息
     */
    async mounts() {
        const cacheKey = 'disk-mounts';
        return this.executeWithCache(cacheKey, async () => {
            this.validatePlatformSupport('disk.mounts');
            const rawData = await this.adapter.getMounts();
            return this.transformMountPoints(rawData);
        }, this.diskConfig.cacheTTL || 30000);
    }
    /**
     * 获取文件系统信息
     */
    async filesystems() {
        const cacheKey = 'disk-filesystems';
        return this.executeWithCache(cacheKey, async () => {
            this.validatePlatformSupport('disk.filesystems');
            const rawData = await this.adapter.getFileSystems();
            return this.transformFileSystems(rawData);
        }, this.diskConfig.cacheTTL || 60000 // 文件系统信息变化较少
        );
    }
    /**
     * 获取磁盘空间总览
     */
    async spaceOverview() {
        const cacheKey = 'disk-space-overview';
        return this.executeWithCache(cacheKey, async () => {
            const usageResult = await this.usage();
            if (!usageResult.success || !usageResult.data) {
                throw new Error('Failed to get disk usage data');
            }
            let totalBytes = 0;
            let usedBytes = 0;
            let availableBytes = 0;
            for (const disk of usageResult.data) {
                if (this.diskConfig.excludeTypes &&
                    this.diskConfig.excludeTypes.includes(disk.filesystem)) {
                    continue;
                }
                totalBytes += disk.total.toBytes();
                usedBytes += disk.used.toBytes();
                availableBytes += disk.available.toBytes();
            }
            const usagePercentage = totalBytes > 0 ? (usedBytes / totalBytes) * 100 : 0;
            return {
                total: new types_1.DataSize(totalBytes),
                used: new types_1.DataSize(usedBytes),
                available: new types_1.DataSize(availableBytes),
                usagePercentage: Math.round(usagePercentage * 100) / 100,
                disks: usageResult.data.length
            };
        }, this.diskConfig.cacheTTL || 15000);
    }
    /**
     * 获取磁盘健康状态检查
     */
    async healthCheck() {
        const cacheKey = 'disk-health';
        return this.executeWithCache(cacheKey, async () => {
            const issues = [];
            const checks = {
                spaceUsage: true,
                mountStatus: true,
                ioErrors: true
            };
            // 检查磁盘空间使用率
            try {
                const usageResult = await this.usage();
                if (usageResult.success && usageResult.data) {
                    for (const disk of usageResult.data) {
                        if (disk.usagePercentage > 90) {
                            issues.push(`High disk usage on ${disk.mountpoint}: ${disk.usagePercentage.toFixed(1)}%`);
                            checks.spaceUsage = false;
                        }
                        else if (disk.usagePercentage > 80) {
                            issues.push(`Disk usage warning on ${disk.mountpoint}: ${disk.usagePercentage.toFixed(1)}%`);
                        }
                    }
                }
            }
            catch (error) {
                issues.push('Failed to check disk usage');
                checks.spaceUsage = false;
            }
            // 检查挂载状态
            try {
                const mountsResult = await this.mounts();
                if (mountsResult.success && mountsResult.data) {
                    const readOnlyMounts = mountsResult.data.filter(mount => mount.options.includes('ro') && !mount.mountpoint.startsWith('/proc'));
                    if (readOnlyMounts.length > 0) {
                        issues.push(`Read-only filesystems detected: ${readOnlyMounts.map(m => m.mountpoint).join(', ')}`);
                        checks.mountStatus = false;
                    }
                }
            }
            catch (error) {
                issues.push('Failed to check mount status');
                checks.mountStatus = false;
            }
            // 确定整体健康状态
            let status = 'healthy';
            if (!checks.spaceUsage || !checks.mountStatus || !checks.ioErrors) {
                status = 'critical';
            }
            else if (issues.length > 0) {
                status = 'warning';
            }
            return {
                status,
                issues,
                checks
            };
        }, this.diskConfig.cacheTTL || 30000);
    }
    /**
     * 配置是否包含 I/O 统计
     */
    withStats(include) {
        this.diskConfig.includeStats = include;
        return this;
    }
    /**
     * 配置排除的文件系统类型
     */
    withExcludeTypes(types) {
        this.diskConfig.excludeTypes = types;
        return this;
    }
    /**
     * 配置只监控指定的挂载点
     */
    withMountPoints(mountPoints) {
        this.diskConfig.mountPoints = mountPoints;
        return this;
    }
    /**
     * 配置磁盘单位
     */
    withUnit(unit) {
        this.diskConfig.unit = unit;
        return this;
    }
    /**
     * 获取默认配置
     */
    getDefaultConfig() {
        return {
            interval: 5000,
            timeout: 10000,
            cacheEnabled: true,
            cacheTTL: 15000,
            samples: 1,
            includeDetails: true,
            includeStats: false, // I/O 统计可能对性能有影响
            excludeTypes: ['proc', 'sysfs', 'devtmpfs', 'tmpfs', 'devpts'],
            unit: 'GB'
        };
    }
    // 私有转换方法
    /**
     * 转换磁盘基本信息
     */
    transformDiskInfo(rawData) {
        if (!Array.isArray(rawData)) {
            return [];
        }
        return rawData.map(disk => ({
            device: disk.device || disk.name || 'unknown',
            mountpoint: disk.mountPoint || disk.mount || '/',
            filesystem: disk.filesystem || disk.fs || disk.type || 'unknown',
            total: new types_1.DataSize(this.safeParseNumber(disk.total || disk.size)),
            used: new types_1.DataSize(this.safeParseNumber(disk.used)),
            available: new types_1.DataSize(this.safeParseNumber(disk.available || disk.free)),
            usagePercentage: this.calculateUsagePercentage(disk),
            type: this.normalizeDeviceType(disk.type || disk.device),
            model: disk.model,
            serial: disk.serial,
            interface: disk.interface
        }));
    }
    /**
     * 转换磁盘使用情况
     */
    transformDiskUsage(rawData) {
        if (!Array.isArray(rawData)) {
            return [];
        }
        return rawData
            .filter(disk => this.shouldIncludeDisk(disk))
            .map(disk => ({
            device: disk.device || disk.filesystem || 'unknown',
            mountpoint: disk.mountPoint || disk.mount || '/',
            filesystem: disk.filesystem || disk.fs || disk.type || 'unknown',
            total: new types_1.DataSize(this.safeParseNumber(disk.total || disk.size)),
            used: new types_1.DataSize(this.safeParseNumber(disk.used)),
            available: new types_1.DataSize(this.safeParseNumber(disk.available || disk.free)),
            usagePercentage: this.calculateUsagePercentage(disk)
        }));
    }
    /**
     * 转换磁盘 I/O 统计
     */
    transformDiskStats(rawData) {
        if (!Array.isArray(rawData)) {
            return [];
        }
        return rawData.map(stats => {
            const readCount = this.safeParseNumber(stats.reads || stats.read_ios);
            const writeCount = this.safeParseNumber(stats.writes || stats.write_ios);
            const readSectors = stats.readSectors ?? stats.read_sectors;
            const writeSectors = stats.writeSectors ?? stats.write_sectors;
            const readBytesRaw = stats.readBytes ?? stats.read_bytes;
            const writeBytesRaw = stats.writeBytes ?? stats.write_bytes;
            // Linux 适配器默认返回扇区数量，需要在此统一换算为字节；如果已有明确字节值则直接使用
            const readSectorsValue = readSectors !== undefined ? this.safeParseNumber(readSectors) : 0;
            const writeSectorsValue = writeSectors !== undefined ? this.safeParseNumber(writeSectors) : 0;
            const readBytesValue = readBytesRaw !== undefined && readBytesRaw !== null
                ? this.safeParseNumber(readBytesRaw)
                : readSectorsValue * 512;
            const writeBytesValue = writeBytesRaw !== undefined && writeBytesRaw !== null
                ? this.safeParseNumber(writeBytesRaw)
                : writeSectorsValue * 512;
            return {
                device: stats.device || 'unknown',
                readCount,
                writeCount,
                readBytes: new types_1.DataSize(readBytesValue),
                writeBytes: new types_1.DataSize(writeBytesValue),
                readTime: this.safeParseNumber(stats.readTime || stats.read_ticks),
                writeTime: this.safeParseNumber(stats.writeTime || stats.write_ticks),
                ioTime: this.safeParseNumber(stats.ioTime || stats.io_ticks),
                weightedIOTime: this.safeParseNumber(stats.weightedIOTime || stats.time_in_queue)
            };
        });
    }
    /**
     * 转换挂载点信息
     */
    transformMountPoints(rawData) {
        if (!Array.isArray(rawData)) {
            return [];
        }
        return rawData.map(mount => ({
            device: mount.device || mount.source || 'unknown',
            mountpoint: mount.mountPoint || mount.target || mount.mount || '/',
            filesystem: mount.filesystem || mount.fstype || mount.type || 'unknown',
            options: (mount.options || mount.opts || '').toString(),
            dump: this.safeParseNumber(mount.dump),
            pass: this.safeParseNumber(mount.pass)
        }));
    }
    /**
     * 转换文件系统信息
     */
    transformFileSystems(rawData) {
        if (!Array.isArray(rawData)) {
            return [];
        }
        return rawData.map(fs => ({
            name: fs.name || fs.filesystem || 'unknown',
            type: fs.type || fs.fstype || 'unknown',
            description: fs.description || '',
            supported: fs.supported !== false,
            features: fs.features || []
        }));
    }
    /**
     * 计算使用率百分比
     */
    calculateUsagePercentage(disk) {
        const total = this.safeParseNumber(disk.total || disk.size);
        const used = this.safeParseNumber(disk.used);
        if (total <= 0) {
            return 0;
        }
        return Math.round((used / total) * 10000) / 100; // 保留两位小数
    }
    /**
     * 判断是否应该包含该磁盘
     */
    shouldIncludeDisk(disk) {
        const filesystem = disk.filesystem || disk.fs || disk.type || '';
        // 排除指定的文件系统类型
        if (this.diskConfig.excludeTypes &&
            this.diskConfig.excludeTypes.includes(filesystem)) {
            return false;
        }
        // 如果配置了特定挂载点，只包含这些挂载点
        if (this.diskConfig.mountPoints && this.diskConfig.mountPoints.length > 0) {
            // 适配不同来源字段（mountPoint/mountpoint/mount），确保定向监控精确生效
            const mountPoint = disk.mountPoint || disk.mountpoint || disk.mount || '/';
            return this.diskConfig.mountPoints.includes(mountPoint);
        }
        return true;
    }
    /**
     * 规范化设备类型
     */
    normalizeDeviceType(type) {
        if (!type)
            return 'Unknown';
        const normalizedType = type.toLowerCase();
        if (normalizedType.includes('ssd'))
            return 'SSD';
        if (normalizedType.includes('hdd') || normalizedType.includes('hard'))
            return 'HDD';
        if (normalizedType.includes('nvme'))
            return 'NVMe';
        if (normalizedType.includes('emmc'))
            return 'eMMC';
        return 'Unknown';
    }
    /**
     * 安全解析数字
     */
    safeParseNumber(value) {
        if (typeof value === 'number') {
            return isNaN(value) ? 0 : value;
        }
        if (typeof value === 'string') {
            const parsed = parseFloat(value);
            return isNaN(parsed) ? 0 : parsed;
        }
        return 0;
    }
    // ==================== 向后兼容的同步方法 ====================
    /**
     * 获取指定路径的空闲磁盘空间（同步版本，向后兼容）
     * @param path 路径（默认为根目录）
     * @returns 空闲磁盘空间对象或 'not supported'
     */
    free(path = '/') {
        try {
            // 对于同步版本，我们无法调用异步的适配器方法
            // 这里返回一个基本的结构，实际值需要通过异步方法获取
            return {
                size: 0, // 总大小
                used: 0, // 已用空间
                available: 0 // 可用空间
            };
        }
        catch (error) {
            return 'not supported';
        }
    }
    /**
     * 获取指定路径的已用磁盘空间（同步版本，向后兼容）
     * @param path 路径（默认为根目录）
     * @returns 已用磁盘空间对象或 'not supported'
     */
    used(path = '/') {
        try {
            // 对于同步版本，我们无法调用异步的适配器方法
            // 这里返回一个基本的结构，实际值需要通过异步方法获取
            return {
                size: 0, // 总大小
                used: 0, // 已用空间
                available: 0 // 可用空间
            };
        }
        catch (error) {
            return 'not supported';
        }
    }
}
exports.DiskMonitor = DiskMonitor;
//# sourceMappingURL=disk-monitor.js.map