const fs = require("fs");
const path = require("path");
const { localGet, localSave } = require("./lib/unit");
const logger = require("./lib/logger");

// 默认编码器配置（Arduino Nano Mini 串口方式）
const defaultEncoderConfig = {
  enabled: false,
  baudRate: 115200,  // 串口波特率
  ppr: 100,          // 每转脉冲数
  intervalMs: 1000,   // 更新间隔
  wheelDiameterMm: 50.8,  // 车轮直径(2英寸=50.8mm)
  speedUnit: "km/h",  // 速度单位
  speedLabel: "车速",
  rpmLabel: "转速",
  directionLabel: "方向",
  showRpm: true,
  showDirection: false,
  invert: false,      // 方向反转
};

const encoderConfigPath = path.resolve(__dirname, "..", "lib", "encoder.config.json");

// 加载编码器配置
const loadEncoderConfig = () => {
  const fileConfig = localGet(encoderConfigPath);
  const merged = { ...defaultEncoderConfig, ...fileConfig };
  if (!fs.existsSync(encoderConfigPath)) {
    localSave(encoderConfigPath, merged);
  }
  return merged;
};

// 归一化速度单位
const normalizeSpeedUnit = (unit) => {
  const key = String(unit || "").toLowerCase();
  if (["mps", "m/s", "ms"].includes(key)) return "m/s";
  if (["kmh", "km/h", "kph"].includes(key)) return "km/h";
  if (["mph"].includes(key)) return "mph";
  return "km/h";
};

// 根据RPM计算速度
const calcSpeedFromRpm = (rpm, config) => {
  const diameterMm = Number(config.wheelDiameterMm) || 0;
  const circumferenceMm = Number(config.wheelCircumferenceMm) || 0;
  const circumferenceM = (circumferenceMm > 0 ? circumferenceMm : Math.PI * diameterMm) / 1000;
  if (!circumferenceM || !Number.isFinite(circumferenceM)) {
    return { speed: 0, unit: normalizeSpeedUnit(config.speedUnit) };
  }

  const speedMps = (rpm * circumferenceM) / 60;
  const unit = normalizeSpeedUnit(config.speedUnit);
  if (unit === "m/s") return { speed: speedMps, unit };
  if (unit === "mph") return { speed: speedMps * 2.236936, unit };
  return { speed: speedMps * 3.6, unit };
};

let encoderInstance = null;
let encoderConfig = loadEncoderConfig();

// 编码器类
class EncoderModule {
  constructor() {
    this.encoder = null;
    this.handler = null;
    this.isRunning = false;
  }

  // 启动编码器
  async start(config, handler, broadcaster) {
    if (this.isRunning) {
      this.stop();
    }

    if (!config.enabled) {
      logger.info("编码器未启用，跳过启动");
      return;
    }

    // 保存handler和broadcaster引用
    this.handler = handler;
    this.broadcaster = broadcaster;

    try {
      // 尝试使用串口库连接Arduino Nano
      let SerialPort;
      try {
        SerialPort = require('serialport');
      } catch (e) {
        logger.warn("串口库不可用，编码器功能已禁用");
        return;
      }

      // 查找Arduino Nano串口设备
      const ports = await SerialPort.list();
      let arduinoPort = null;
      
      for (const port of ports) {
        // 查找可能的Arduino设备
        if (port.manufacturer && port.manufacturer.toLowerCase().includes('arduino')) {
          arduinoPort = port.path;
          break;
        }
        // 也可能通过VID/PID识别
        if (port.vendorId && port.productId) {
          // Arduino Nano的常见VID/PID
          if ((port.vendorId.toLowerCase() === '2341' && port.productId.toLowerCase() === '0043') ||
              (port.vendorId.toLowerCase() === '1a86' && port.productId.toLowerCase() === '7523')) {
            arduinoPort = port.path;
            break;
          }
        }
      }

      if (!arduinoPort) {
        logger.warn("未找到Arduino Nano设备，编码器功能已禁用");
        return;
      }

      // 连接串口
      this.serialPort = new SerialPort({
        path: arduinoPort,
        baudRate: Number(config.baudRate) || 115200,
        dataBits: 8,
        stopBits: 1,
        parity: 'none'
      });

      this.handler = handler;

      // 处理串口数据
      this.serialPort.on('data', (data) => {
        const line = data.toString().trim();
        if (line.startsWith('Speed:')) {
          try {
            const speedValue = parseFloat(line.replace('Speed:', ''));
            if (!isNaN(speedValue)) {
              // 根据配置决定是否反转方向
              const actualSpeedValue = config.invert ? -speedValue : speedValue;
              const direction = actualSpeedValue >= 0 ? "正转" : "反转";
              
              // 构造编码器数据对象
              const payload = {
                rpm: this.calculateRpmFromSpeed(Math.abs(actualSpeedValue), config),
                speed: Math.abs(actualSpeedValue).toFixed(2),
                unit: config.speedUnit,
                direction: direction,
                count: Date.now() // 使用时间戳作为计数参考
              };

              if (this.handler) {
                this.handler(payload);
              }
              
              // 如果提供了广播函数，广播编码器数据
              if (this.broadcaster) {
                this.broadcaster('encoder-data', payload);
              }
            }
          } catch (parseError) {
            logger.warn("解析Arduino数据失败: " + parseError.message);
          }
        }
      });

      this.serialPort.on('error', (err) => {
        logger.error("串口错误: " + err.message);
        this.stop();
      });

      this.isRunning = true;
      logger.info(`编码器串口连接成功，设备: ${arduinoPort}`);

    } catch (error) {
      logger.warn("编码器启动失败，功能已禁用: " + error.message);
      return; // 直接返回，不使用模拟模式
    }
  }

  // 根据速度值计算RPM
  calculateRpmFromSpeed(speedKmh, config) {
    // 基于轮子周长计算RPM
    const wheelCircumferenceMm = config.wheelDiameterMm * Math.PI; // 轮子周长(mm)
    const speedMmPerMin = (speedKmh * 1000000) / 60; // 转换为mm/min
    const rpm = speedMmPerMin / wheelCircumferenceMm;
    return rpm;
  }



  // 停止编码器
  stop() {
    if (this.encoder) {
      this.encoder.removeAllListeners();
      this.encoder = null;
    }
    
    // 关闭串口连接
    if (this.serialPort) {
      this.serialPort.close();
      this.serialPort = null;
    }
    
    this.handler = null;
    this.isRunning = false;
    logger.info("编码器已停止");
  }

  // 更新配置
  updateConfig(newConfig) {
    encoderConfig = { ...encoderConfig, ...newConfig };
    localSave(encoderConfigPath, encoderConfig);
    
    // 如果编码器正在运行，重启它
    if (this.isRunning) {
      this.start(encoderConfig, this.handler);
    }
  }

  // 获取当前配置
  getConfig() {
    return encoderConfig;
  }

  // 获取状态
  getStatus() {
    return {
      isRunning: this.isRunning,
      config: this.getConfig()
    };
  }
}

// 创建单例实例
const encoderModule = new EncoderModule();

// 导出API
module.exports = {
  encoderModule,
  loadEncoderConfig,
  calcSpeedFromRpm,
  normalizeSpeedUnit,
  defaultEncoderConfig
};