const ADS1115 = require("ads1115");
const EventEmitter = require("events");
const fs = require("fs");
const { sleep } = require("../lib/unit.js");
require("../lib/logger.js");

const GAIN_TO_FSR = {
  "2/3": 6.144,
  "0.6666666666666666": 6.144,
  "1": 4.096,
  "2": 2.048,
  "4": 1.024,
  "8": 0.512,
  "16": 0.256,
};

class Ad extends EventEmitter {
  constructor() {
    super();

    this.voltage = 0;
    this.voltages = [0, 0, 0, 0];
    this.maxVoltage = 0;

    if (!fs.existsSync("/dev/i2c-1")) {
      logger.warn("/dev/i2c-1 不存在，跳过 ADS1115 初始化");
      return;
    }

    ADS1115.open(1, 0x48)
      .then(async (ads1115) => {
        const gainEnv = process.env.NETWORK_RC_ADC_GAIN;
        const scale = Number(process.env.NETWORK_RC_ADC_SCALE || 1);
        const minVoltage = Number(process.env.NETWORK_RC_ADC_MIN_VOLTAGE || 0.01);

        if (gainEnv !== undefined && gainEnv !== "") {
          const gainValue = Number(gainEnv);
          if (Number.isFinite(gainValue) && gainValue > 0) {
            ads1115.gain = gainValue;
          }
        } else {
          ads1115.gain = 1;
        }

        const fsrEnv = Number(process.env.NETWORK_RC_ADC_FSR);
        const fsr = Number.isFinite(fsrEnv)
          ? fsrEnv
          : GAIN_TO_FSR[String(ads1115.gain)] || 4.096;

        logger.info(
          `ADS1115 gain=${ads1115.gain}, FSR=${fsr}V, scale=${scale}`
        );

        const channels = ["0+GND", "1+GND", "2+GND", "3+GND"];
        const isVerbose = process.env.NETWORK_RC_ADC_VERBOSE === "1";

        while (true) {
          const nextVoltages = [];
          for (let i = 0; i < channels.length; i++) {
            const raw = await ads1115.measure(channels[i]);
            let voltage;

            if (Math.abs(raw) > 100) {
              voltage = raw * (fsr / 32768);
            } else {
              voltage = raw;
            }

            voltage = voltage * scale;
            nextVoltages[i] = Math.abs(voltage) < minVoltage ? 0 : voltage;
          }

          const changed = nextVoltages.some(
            (v, i) => this.voltages[i].toFixed(2) !== v.toFixed(2)
          );

          if (changed) {
            this.voltages = nextVoltages;
            this.voltage = nextVoltages[0] || 0;
            this.emit("voltages-change", nextVoltages);
            this.emit("voltage-change", this.voltage);
            if (isVerbose) {
              logger.info(
                `voltages: ${nextVoltages
                  .map((v) => v.toFixed(2))
                  .join(",")}`
              );
            }
          }

          await sleep(2000);
        }
      })
      .catch((err) => {
        logger.error("AD 错误" + err.message);
      });
  }
}

module.exports = new Ad();
