import htmlParseStringify from "html-parse-stringify";
import TextRender from "./textRender";

function dhCalTime(sp, length, speed) {
  if (sp === "tencent") {
    return length * 220;
  }
  let times;
  switch (speed) {
    case 5:
    default:
      times = 250;
      break;
    case 4:
      times = 300;
      break;
    case 3:
      times = 350;
      break;
    case 2:
      times = 400;
      break;
  }
  return length * times;
}

function calSleep(sp, text) {
  let delay = 0;
  const asts = htmlParseStringify.parse(text);
  asts.forEach((elem) => {
    elem.children.forEach((tag) => {
      if (
        tag.type === "tag" &&
        (tag.name === "break" || tag.name === "silence")
      ) {
        if (tag.attrs["time"]) {
          const second = tag.attrs["time"].match(/\d*\.?\d+(?=s)/gi);
          if (second && second[0]) {
            delay += 1000 * second[0];
            return;
          }
          const millisecond = tag.attrs["time"].match(/\d*\.?\d+(?=ms)/gi);
          if (millisecond && millisecond[0]) {
            delay += millisecond[0];
          }
        }
      }
    });
  });
  return delay
}

function genSSML(text, config, sp) {
  let ssml = "";
  console.log("genSSML :>> ", text, config, sp);

  let tmp = "";
  config.property.forEach((prop) => {
    if (prop[sp]) {
      tmp += " " + prop.name + '="' + prop[sp] + '" ';
    }
  });
  if (tmp) {
    ssml = "<" + config.tag + tmp;
    if (config.tag === "break") {
      ssml += "/>";
    } else ssml += " >" + text + "</" + config.tag + ">";
  }

  return ssml;
}

function dhCalSSML(speech) {
  let text = "";
  let index = 0;
  speech.config?.forEach((set) => {
    text += speech.text.slice(index, set.place[0]);
    let temp = speech.text.slice(set.place[0], set.place[1]);
    let ssml = genSSML(temp, set.val, speech.sp);
    text += ssml;
    index = set.place[1];
  });
  text += speech.text.slice(index);
  text = "<speak>" + text + "</speak>";
  return text;
}

function calTime(speechs, config) {
  for (let i = 0; i < speechs.length; i++) {
    // speechs.index = i;

    switch (speechs[i].type) {
      case "dh":
        speechs[i].time = dhCalTime(
          speechs[i].sp,
          speechs[i].text.length,
          config?.speed
        );
        speechs[i].text = dhCalSSML(speechs[i]);
        speechs[i].time += calSleep(speechs[i].sp, speechs[i].text);

        switch (speechs[i].sp) {
          case "tencent":
            speechs[i].delay = -2500;
            break;
          default:
            speechs[i].delay = 0;
            break;
        }
        break;
      case "tts":
        break;
      case "video":
        break;
      default:
        break;
    }
  }
  return speechs;
}

class contentsManager {
  constructor(config = {}) {
    this.tts = new TTS(config.tts);
    // this.drama = new Drama();
    this.callback = null;
  }

  async setData(speechs, config = {}) {
    const tmp = calTime(speechs, config.dh);
    const res = await this.tts.genDataAndTTS(tmp, config.tts);
    return res;
  }
}

export function initContentsManager() {
  return new contentsManager(...arguments);
}

class TTS {
  constructor(config) {
    this.textRender = new TextRender(config);
  }

  async genDataAndTTS(speechs, config) {
    const speechRes = [...speechs];
    const drama = {};
    for (let i = 0; i < speechs.length; i++) {
      if (speechs[i].type === "tts") {
        speechs[i].sourceIndex = i;
        drama[speechs[i].role]
          ? drama[speechs[i].role].push({ ...speechs[i] })
          : (drama[speechs[i].role] = [{ ...speechs[i] }]);
      }
    }
    for (const key in drama) {
      const result = await this.textRender.ttsRender(drama[key], key, config);
      result.forEach((speech) => {
        speechRes[speech.sourceIndex] = { ...speech };
        delete speechRes[speech.sourceIndex].sourceIndex;
      });
    }
    return speechRes;
  }

  async genData(speechs) {
    // console.log("tts", data);
    const drama = {};
    const resource = {};
    speechs.forEach((speech) => {
      if (speech.type === "tts") {
        drama[speech.role]
          ? drama[speech.role].push(speech.text)
          : (drama[speech.role] = [speech.text]);
      }
    });
    const ssmls = this.genSSML(drama);
    console.log("ssml", ssmls);
    for (const key in ssmls) {
      resource[key] = await this.SSML2Audio(ssmls[key]);
    }
    return resource;
  }

  async speechs2Audio(speechs) {}

  async SSML2Audio(ssml) {
    // const result = await axios({});
    // return result.data;
    const result = await axios({
      method: "post",
      url: "https://hz-test.ikandy.cn:60010/tts/short",
      data: {
        ttsId: 9,
        Text: ssml,
        Codec: "mp3",
        SampleRate: 16000,
        Speed: 0,
        Volume: 0,
      },
    });
    // console.log('SSML2Audio :>> ', result.data);
    return result.data.data.voice;
  }

  genSSML(drama) {
    const ssmls = {};
    Object.keys(drama).forEach((property) => {
      let ssml = "<speak>" + this.setBreak("500");
      // let ssml = "";
      drama[property].forEach((text) => {
        ssml += text;
        ssml += this.setBreak("1000");
      });
      ssmls[property] =
        ssml.substring(0, ssml.length - this.setBreak("1000").length) +
        "</speak>";
      // ssml;
    });
    return ssmls;
  }

  setBreak(timer) {
    return `<break time="${timer}ms"/>`;
  }
}

// class Drama {
//   constructor() {}

//   genData(speechs) {
//     const timeLine = [];
//     const roleTimesTable = {};
//     speechs.forEach((speech) => {
//       const speechResult = this.transform(speech);
//       if (speech.type === "tts") {
//         if (roleTimesTable[speechResult.role]) {
//           speechResult.startTime = roleTimesTable[speechResult.role];
//           roleTimesTable[speechResult.role] += speechResult.endTime / 1000;
//         } else {
//           speechResult.startTime = 0;
//           roleTimesTable[speechResult.role] = speechResult.endTime / 1000;
//         }
//       }
//       timeLine.push(speechResult);
//     });
//     console.log("drama", timeLine, roleTimesTable);
//     return timeLine;
//   }

//   transform(speech) {
//     let result;
//     switch (speech.type) {
//       case "tts":
//       case "dh":
//         result = {
//           ...speech,
//           time: 500,
//           endTime: speech.holdTime,
//           waitLast: speech.waitLast === void 0 ? false : speech.waitLast,
//         };
//         break;
//       default:
//         result = {
//           ...speech,
//           delay: 0,
//           endTime: 0,
//         };
//         break;
//     }
//     return result;
//   }
// }
