const { FileOperationMachine } = require("../../connect/file");
const EventEmitter = require("events");
const roomManager = require("../../../SDK/licodeSDK/roomManager");
const { default: dmDriver } = require("../../service/DM/DMDriver");
const { default: axios } = require("axios");
const { RtcSDK } = require("../../service/RTC/rtcSDK");
const Logger = require('../../../utils/logger').Logger;
let logger = new Logger(__filename);

class ISource {
  constructor(iSource, context) {
    Object.assign(this, iSource, context);
    this.connectStateMachine;
    this.eventEmitter = new EventEmitter();
    this.state = "init";
  }
  update(iSink) {
    Object.assign(this, iSink);
  }

  mutationUpdate(iSink) {
    this.close();
    Object.assign(this, iSink);
    this.open();
  }
  async open() {
    this.state = "init";
    if (this.connectType == "pub") {
      if (this.config.sdkType == "licode") {
        this.room = roomManager.connect(this.config.token, "main", (result) => { });
        if (this.room) {
          this.room.then(() => {
            this.eventEmitter.on("sendLicodeMessage", this.sendLicodeMessage);
          });
        } else {
          this.eventEmitter.removeListener("sendLicodeMessage", this.sendLicodeMessage);
          this.eventEmitter.on("sendLicodeMessage", this.sendLicodeMessage);
        }
        if (this.config.driveType == "dmDrive") {
          this.dmDriver = new dmDriver(this.sessionId);
          this.dmDriver.onOutput = (event) => {
            let licodeMessage = getLicodeMessage(this.sessionId, this.config.roomId, event.event, this.config.receivers)
            this.eventEmitter.emit("sendLicodeMessage", licodeMessage);
          };
        }
      }
    } else if (this.connectType == "rtc") {
      this.rtc = new RtcSDK({});
      this.rtc.joinRoom({ roomId: this.config.roomId, target: this.config.target });
    }
  } 
  close() {
    this.state = "cancelled";
    if (this.connectType == "rtc") {
      this.rtc?.leaveRoom();
    }
  }

  async start(params, data) {
    this.state = "running";
    if (data == "success") {
      this.eventEmitter.emit("start", data);
      return "success";
    }
    if (this.connectType == "rest") {
      // axios({
      //   url: onCallback.url,
      //   method: "POST",
      //   headers: {
      //     "Content-Type": "application/json",
      //   },
      //   data: res,
      // });
      console.log("sink.onComplete:", this.config.url, data);
    } else if (this.connectType == "dmhub") {
      //传入会话中控
      sendDmHub(this, data);
    } else if (this.connectType == "invoke") {
      return data;
    } else if (this.connectType == "pub") {
      if (this.config.sdkType == "licode") {
        console.log("licode", data);
        //TODO 驱动方式
        if (this.config.driveType == "dmDrive") {
          let sayAction = data.event.param.bot.actions;
          let actionData = getOldDMDriverData(sayAction);
          this.dmDriver.drive(actionData);
        } else {
          let licodeMessage = getLicodeMessage(this.sessionId, this.config.roomId, data, this.config.receivers)
          this.eventEmitter.emit("sendLicodeMessage", licodeMessage);
        }
      }
    } else if (this.connectType == "transformer") {
      sendTransformer(this, data);
    } else if (this.connectType == "rtc") {
      if (this.serviceName == "DH") {
        this.rtc.pushStream({ video: data.result.url, audio: data.result.url });
      }
    }
    this.eventEmitter.emit("start", "success");
  }

  stop() { }

  pause() { }

  resume() { }

  async query(params, data) {
    this.state = "running";
    if (data == "success") {
      this.eventEmitter.emit("query", data);
    }
    if (this.connectType == "rest") {
      // axios({
      //   url: onCallback.url,
      //   method: "POST",
      //   headers: {
      //     "Content-Type": "application/json",
      //   },
      //   data: res,
      // });
      console.log("sink.onComplete:", this.config.url, data);
    } else if (this.connectType == "dmhub") {
      //传入会话中控
      sendDmHub(this, data);
    } else if (this.connectType == "invoke") {
      return data;
    } else if (this.connectType == "transformer") {
      sendTransformer(this, data);
    } else if (this.connectType == "rtc") {
      if (this.serviceName == "TTS") {
        console.log("TTS push RTC", this.rtc.roomId, this.rtc.peerId, await this.rtc.roomStats());
        this.rtc.pushTTS(data.result.base64);
      }
    }
    this.eventEmitter.emit("query", "success");
  }

  async getTaskStatus(params, data) {
    this.state = "running";
    if (data == "success") {
      return "success";
    }
    if (this.connectType == "rest") {
      // axios({
      //   url: onCallback.url,
      //   method: "POST",
      //   headers: {
      //     "Content-Type": "application/json",
      //   },
      //   data: res,
      // });
      console.log("sink.onComplete:", this.config.url, data);
    } else if (this.connectType == "dmhub") {
      //传入会话中控
      sendDmHub(this, data);
    } else if (this.connectType == "invoke") {
      return data;
    }
    return "success";
  }

  sendLicodeMessage(msg) {
    try {
      roomManager.sendGenericMessage(msg);
    } catch (e) {
      logger.error("sendLicodeMessage", e);
    }
  }
}

function getLicodeMessage(sessionId, roomId, data, receivers, to) {
  return {
    roomId: roomId,
    data: {
      sessionId: sessionId,
      event: data,
      to: to || "client",
      sourceRoom: roomId,
    },
    options: {
      receivers: receivers,
    },
  };
}

function getOldDMDriverData(sayAction) {
  var dmDriverDatas = {
    type: "lazy",
    data: [],
  };
  for (var action of sayAction) {
    var data = {
      text: action.say,
      role: "bot",
      type: "tts",
      sp: "unit_public_v3",
    };
    dmDriverDatas.data.push(data);
  }
  return dmDriverDatas;
}

async function sendDmHub(iSink, data) {
  var params = iSink.config.params;
  params.data = { text: data.result.text };
  var options = {
    url: iSink.config.url,
    method: "PUT",
    data: params
  }
  console.log("sendDmHub", options);
  axios(options);
}

async function sendTransformer(iSink, data) {
  //构建params
  console.log("sendTransformer", data);
  var params = Object.assign({}, iSink.config.params);
  for (var key in params) {
    params[key] = data.result[iSink.config.params[key]];
  }
  params.instanceId = iSink.config.instanceId;
  params.targetId = iSink.config.targetId;
  var options = {
    url: `${iSink.config.url}/${iSink.config.type}${iSink.config.path}`,
    method: "POST",
    data: params
  }
  console.log("sendTransformer", options);
  axios(options);
}

module.exports.ISink = ISource;
