const { EventEmitter } = require("events");
const { execSync } = require("child_process");

class Microphone extends EventEmitter {
  constructor(options) {
    super(options);
    this.options = options;
    this.list = [];
    this.playing = false;
    this.streamer = undefined;
    this.pactlAvailable = true;
  }

  ensurePulse() {
    if (!this.pactlAvailable) return false;
    try {
      execSync("LANG=en pactl info");
      return true;
    } catch (e) {
      this.pactlAvailable = false;
      logger.warn("pactl 不可用，麦克风设备相关功能将不可用");
      return false;
    }
  }

  /**
   * 获取麦克风设备列表
   */
  async getMicphoneList() {
    if (!this.ensurePulse()) {
      logger.warn("pactl 不可用，跳过获取麦克风设备列表");
      this.list = [];
      return [];
    }

    let output = "";
    try {
      output = execSync("LANG=en pactl list sources").toString();
    } catch (e) {
      logger.warn("pactl 不可用，跳过获取麦克风设备列表");
      this.list = [];
      return [];
    }

    const matchList = Array.from(
      output.matchAll(
        /Source #(\d+)[\s\S]+?Name: (.+)[\s\S]+?Description: (.+)[\s\S]+?Volume: [\s\S]+?(\d+)\%/g
      )
    );

    const list = matchList.map(([, index, name, description, volume]) => ({
      index,
      displayName: description,
      name,
      volume,
      description,
    }));

    logger.info("获取音频设备列表", list);
    this.list = list;
    return list;
  }

  // 获取当前播麦克风
  async getMicphone() {
    if (!this.ensurePulse()) {
      logger.warn("pactl 不可用，无法获取当前麦克风");
      return undefined;
    }

    let output = "";
    try {
      output = execSync("LANG=en pactl info").toString();
    } catch (e) {
      logger.warn("pactl 不可用，无法获取当前麦克风");
      return undefined;
    }

    const [, name] = output.match(/Default Source: (.+?)\n/) || [];
    logger.info("获取当前播麦克风", name);
    const speaker = (await this.getMicphoneList()).find(
      (item) => item.name === name
    );
    logger.info("获取当前播麦克风", speaker);
    return speaker;
  }

  // 设置音频播放设备
  async setMicphone(name) {
    if (!this.ensurePulse()) {
      logger.warn("pactl 不可用，无法设置麦克风");
      return;
    }
    logger.info("设置音频设备", name);
    try {
      execSync(`LANG=en pactl set-default-source ${name}`);
    } catch (e) {
      logger.warn("设置麦克风失败");
    }
  }

  // 设置音频播放设备音量
  async setMicphoneVolume(name, v) {
    if (!this.ensurePulse()) {
      logger.warn("pactl 不可用，无法设置麦克风音量");
      return;
    }
    logger.info("设置音频设备音量", name, v);
    try {
      execSync(`LANG=en pactl set-source-volume ${name} ${v}%`);
    } catch (e) {
      logger.warn("设置麦克风音量失败");
    }
  }
}

module.exports = new Microphone();
