/**
 * VCD (Value Change Dump) 解析器
 * 纯 TypeScript 实现，参照 VerilogCoder 项目格式
 *
 * @deprecated 当前未使用，保留备用
 * 目前使用 waveformTracer.ts 调用 Python 打包的 waveform_trace.exe
 * 未来可能用此文件替换 Python 实现
 */
import * as fs from 'fs';
import * as path from 'path';

// ==================== 类型定义 ====================

/** 信号定义 */
export interface VcdSignal {
  name: string;           // 完整路径名，如 "tb.top_module.data"
  shortName: string;      // 短名，如 "data"
  symbolId: string;       // VCD 符号 ID，如 "!", "#"
  width: number;          // 位宽
  varType: string;        // 变量类型：wire, reg
  module: string;         // 所属模块
}

/** 时间-值对 */
export interface TimeValue {
  time: number;
  value: string;
}

/** 信号波形数据 */
export interface SignalWaveform {
  signal: VcdSignal;
  changes: TimeValue[];
}

/** VCD 解析结果 */
export interface VcdData {
  date?: string;
  version?: string;
  timescale: string;
  endTime: number;
  signals: Map<string, VcdSignal>;      // symbolId -> signal
  waveforms: Map<string, TimeValue[]>;  // symbolId -> changes
}

/** Mismatch 信息 */
export interface MismatchInfo {
  time: number;
  signal: string;
  dutValue: string;
  refValue: string;
}

// ==================== VCD 解析器 ====================

export class VcdParser {
  private signals: Map<string, VcdSignal> = new Map();
  private waveforms: Map<string, TimeValue[]> = new Map();
  private scopeStack: string[] = [];
  private timescale: string = '1ns';
  private currentTime: number = 0;
  private endTime: number = 0;
  private date?: string;
  private version?: string;

  /**
   * 解析 VCD 文件
   */
  parse(filePath: string): VcdData {
    const content = fs.readFileSync(filePath, 'utf-8');
    return this.parseContent(content);
  }

  /**
   * 解析 VCD 内容
   */
  parseContent(content: string): VcdData {
    // 预处理：将多行指令合并成单行
    const normalizedContent = this.normalizeVcdContent(content);
    const lines = normalizedContent.split('\n');
    let inDefinitions = true;

    for (const rawLine of lines) {
      const line = rawLine.trim();
      if (!line) continue;

      if (inDefinitions) {
        // 解析定义区
        if (line.startsWith('$enddefinitions')) {
          inDefinitions = false;
          continue;
        }
        this.parseDefinition(line);
      } else {
        // 解析数据区
        this.parseValueChange(line);
      }
    }

    return {
      date: this.date,
      version: this.version,
      timescale: this.timescale,
      endTime: this.endTime,
      signals: this.signals,
      waveforms: this.waveforms
    };
  }

  private parseDefinition(line: string): void {
    if (line.startsWith('$date')) {
      this.date = this.extractValue(line);
    } else if (line.startsWith('$version')) {
      this.version = this.extractValue(line);
    } else if (line.startsWith('$timescale')) {
      this.timescale = this.extractValue(line) || '1ns';
    } else if (line.startsWith('$scope')) {
      const match = line.match(/\$scope\s+\w+\s+(\S+)/);
      if (match) {
        this.scopeStack.push(match[1]);
      }
    } else if (line.startsWith('$upscope')) {
      this.scopeStack.pop();
    } else if (line.startsWith('$var')) {
      this.parseVariable(line);
    }
  }

  private parseVariable(line: string): void {
    // $var wire 8 # data [7:0] $end
    // $var reg 1 ! clk $end
    const match = line.match(/\$var\s+(\w+)\s+(\d+)\s+(\S+)\s+(\S+)/);
    if (!match) return;

    const [, varType, widthStr, symbolId, name] = match;
    const width = parseInt(widthStr, 10);
    const module = this.scopeStack.join('.');
    const fullName = module ? `${module}.${name}` : name;

    const signal: VcdSignal = {
      name: fullName,
      shortName: name.replace(/\[\d+:\d+\]/, ''),  // 移除位宽标注
      symbolId,
      width,
      varType,
      module
    };

    this.signals.set(symbolId, signal);
    this.waveforms.set(symbolId, []);
  }

  private parseValueChange(line: string): void {
    if (line.startsWith('#')) {
      // 时间戳: #100
      this.currentTime = parseInt(line.substring(1), 10);
      this.endTime = Math.max(this.endTime, this.currentTime);
    } else if (line.startsWith('b') || line.startsWith('B')) {
      // 多位值: b10101010 #
      const spaceIdx = line.indexOf(' ');
      if (spaceIdx > 0) {
        const value = line.substring(1, spaceIdx);
        const symbolId = line.substring(spaceIdx + 1).trim();
        this.addChange(symbolId, value);
      }
    } else if (line.length >= 2 && !line.startsWith('$')) {
      // 单位值: 0! 或 1# 或 x$
      const value = line[0];
      const symbolId = line.substring(1).trim();
      if (symbolId && this.signals.has(symbolId)) {
        this.addChange(symbolId, value);
      }
    }
  }

  private addChange(symbolId: string, value: string): void {
    const changes = this.waveforms.get(symbolId);
    if (changes) {
      changes.push({ time: this.currentTime, value });
    }
  }

  private extractValue(line: string): string {
    // 提取 $xxx value $end 中的 value
    const match = line.match(/\$\w+\s+(.+?)\s*\$end/);
    return match ? match[1].trim() : '';
  }

  /**
   * 预处理 VCD 内容，将多行指令合并成单行
   */
  private normalizeVcdContent(content: string): string {
    // 将多行 $xxx ... $end 合并成单行
    return content.replace(/(\$\w+)\s*\n\s*([^\$]+?)\s*\n\s*(\$end)/g, '$1 $2 $3');
  }
}

// ==================== 波形分析工具 ====================

/**
 * 二进制字符串转十六进制
 */
export function binaryToHex(binary: string): string {
  if (binary === 'x' || binary === 'X' || binary.includes('x')) {
    return 'xx';
  }
  if (binary === 'z' || binary === 'Z' || binary.includes('z')) {
    return 'zz';
  }
  if (binary.length <= 1) {
    return binary;
  }
  // 补齐到 4 的倍数
  const padded = binary.padStart(Math.ceil(binary.length / 4) * 4, '0');
  let hex = '';
  for (let i = 0; i < padded.length; i += 4) {
    hex += parseInt(padded.substring(i, i + 4), 2).toString(16);
  }
  return hex;
}

/**
 * 获取信号在指定时间的值
 */
export function getValueAtTime(
  changes: TimeValue[],
  time: number
): string {
  let value = 'x';
  for (const change of changes) {
    if (change.time <= time) {
      value = change.value;
    } else {
      break;
    }
  }
  return value;
}

/**
 * 查找 DUT 和 REF 信号的第一个 mismatch
 */
export function findFirstMismatch(
  vcdData: VcdData,
  dutSignals: string[],
  refSignals: string[]
): MismatchInfo | null {
  // 收集所有时间点
  const allTimes = new Set<number>();
  for (const changes of vcdData.waveforms.values()) {
    for (const c of changes) {
      allTimes.add(c.time);
    }
  }
  const sortedTimes = Array.from(allTimes).sort((a, b) => a - b);

  // 按信号名匹配 DUT 和 REF
  for (const time of sortedTimes) {
    for (let i = 0; i < dutSignals.length; i++) {
      const dutSig = findSignalByName(vcdData, dutSignals[i]);
      const refSig = findSignalByName(vcdData, refSignals[i]);

      if (!dutSig || !refSig) continue;

      const dutChanges = vcdData.waveforms.get(dutSig.symbolId) || [];
      const refChanges = vcdData.waveforms.get(refSig.symbolId) || [];

      const dutVal = getValueAtTime(dutChanges, time);
      const refVal = getValueAtTime(refChanges, time);

      // 跳过未知值
      if (dutVal.includes('x') || refVal.includes('x')) continue;

      if (dutVal !== refVal) {
        return {
          time,
          signal: dutSig.shortName,
          dutValue: binaryToHex(dutVal),
          refValue: binaryToHex(refVal)
        };
      }
    }
  }
  return null;
}

/**
 * 按名称查找信号
 */
function findSignalByName(vcdData: VcdData, name: string): VcdSignal | null {
  for (const signal of vcdData.signals.values()) {
    if (signal.name.endsWith(name) || signal.shortName === name) {
      return signal;
    }
  }
  return null;
}

/**
 * 生成波形表格（参照 VerilogCoder 格式）
 */
export function generateWaveformTable(
  vcdData: VcdData,
  signalNames: string[],
  startTime: number = 0,
  endTime?: number,
  windowSize: number = 20
): string {
  const actualEndTime = endTime ?? vcdData.endTime;

  // 查找信号
  const signals: VcdSignal[] = [];
  for (const name of signalNames) {
    const sig = findSignalByName(vcdData, name);
    if (sig) signals.push(sig);
  }

  if (signals.length === 0) {
    return '未找到指定信号';
  }

  // 收集时间点
  const times = new Set<number>();
  for (const sig of signals) {
    const changes = vcdData.waveforms.get(sig.symbolId) || [];
    for (const c of changes) {
      if (c.time >= startTime && c.time <= actualEndTime) {
        times.add(c.time);
      }
    }
  }

  let sortedTimes = Array.from(times).sort((a, b) => a - b);
  if (sortedTimes.length > windowSize) {
    sortedTimes = sortedTimes.slice(0, windowSize);
  }

  // 生成表头
  const headers = ['time(ns)', ...signals.map(s => s.shortName)];
  const colWidths = headers.map(h => Math.max(h.length, 8));

  let table = '### Waveform Trace ###\n';
  table += headers.map((h, i) => h.padEnd(colWidths[i])).join('  ') + '\n';
  table += colWidths.map(w => '─'.repeat(w)).join('──') + '\n';

  // 生成数据行
  for (const time of sortedTimes) {
    const row = [time.toString()];
    for (const sig of signals) {
      const changes = vcdData.waveforms.get(sig.symbolId) || [];
      const val = getValueAtTime(changes, time);
      row.push(binaryToHex(val));
    }
    table += row.map((v, i) => v.padEnd(colWidths[i])).join('  ') + '\n';
  }

  table += '### Waveform Trace End ###\n';
  return table;
}

/**
 * 获取信号显示名称（模块.信号名[位宽]）
 */
function getSignalDisplayName(sig: VcdSignal): string {
  const moduleParts = sig.module.split('.');
  const moduleShort = moduleParts[moduleParts.length - 1] || '';
  const bitInfo = sig.width > 1 ? `[${sig.width - 1}:0]` : '';
  return moduleShort ? `${moduleShort}.${sig.shortName}${bitInfo}` : `${sig.shortName}${bitInfo}`;
}

/**
 * 生成变化日志格式（只记录信号变化）
 */
export function generateChangeLog(vcdData: VcdData): string {
  // 筛选信号（排除 parameter）
  const signals: VcdSignal[] = [];
  for (const sig of vcdData.signals.values()) {
    if (sig.varType !== 'parameter') {
      signals.push(sig);
    }
  }

  // 收集所有时间点
  const times = new Set<number>();
  for (const sig of signals) {
    const changes = vcdData.waveforms.get(sig.symbolId) || [];
    for (const c of changes) {
      times.add(c.time);
    }
  }
  const sortedTimes = Array.from(times).sort((a, b) => a - b);

  // 记录每个信号的上一个值
  const lastValues = new Map<string, string | null>();
  for (const sig of signals) {
    lastValues.set(sig.symbolId, null);
  }

  let log = '';

  for (const time of sortedTimes) {
    const changes: string[] = [];

    for (const sig of signals) {
      const waveform = vcdData.waveforms.get(sig.symbolId) || [];
      const currentVal = binaryToHex(getValueAtTime(waveform, time));
      const lastVal = lastValues.get(sig.symbolId);

      if (lastVal === null) {
        changes.push(`${getSignalDisplayName(sig)}=${currentVal}`);
      } else if (currentVal !== lastVal) {
        changes.push(`${getSignalDisplayName(sig)} ${lastVal}→${currentVal}`);
      }

      lastValues.set(sig.symbolId, currentVal);
    }

    if (changes.length > 0) {
      log += `#${time}: ${changes.join(', ')}\n`;
    }
  }

  return log;
}

/**
 * 分析 VCD 文件（主入口）
 */
export function analyzeVcdFile(
  filePath: string,
  signalFilter?: string,
  checkpoint?: number
): string {
  // 解析 VCD
  const parser = new VcdParser();
  const vcdData = parser.parse(filePath);

  // 解析信号过滤器
  const signalNames = signalFilter
    ? signalFilter.split(',').map(s => s.trim())
    : Array.from(vcdData.signals.values()).map(s => s.shortName);

  // 生成摘要
  let result = `=== VCD 波形分析 ===\n`;
  result += `文件: ${path.basename(filePath)}\n`;
  result += `时间单位: ${vcdData.timescale}\n`;
  result += `仿真时长: 0 - ${vcdData.endTime}${vcdData.timescale}\n\n`;

  // 信号列表
  result += `--- 信号列表 (${vcdData.signals.size} 个) ---\n`;
  let idx = 1;
  for (const sig of vcdData.signals.values()) {
    if (idx <= 10) {
      result += `${idx}. ${sig.shortName} (${sig.width}-bit, ${sig.varType})\n`;
    }
    idx++;
  }
  if (vcdData.signals.size > 10) {
    result += `... 还有 ${vcdData.signals.size - 10} 个信号\n`;
  }
  result += '\n';

  // 变化日志
  result += generateChangeLog(vcdData);

  return result;
}
