const { createMachine, interpret } = require("xstate");
const EventEmitter = require("events");
const fs = require("fs");
const { default: axios } = require("axios");

class HttpChunkMachine {
  constructor() {
    this.stateMachine = createMachine({
      id: "args",
      initial: "idle",
      predictableActionArguments: true,
      states: {
        idle: {
          on: {
            START: { target: "requesting" },
          },
        },
        requesting: {
          invoke: {
            src: this.request,
            onDone: {
              target: "responsing",
            },
            onError: {
              target: "error",
              actions: [this.setError],
            },
          },
        },
        responsing: {
          on: {
            CLOSE: { target: "idle" },
            ERROR: { target: "error" },
          },
        },
        error: {
          on: {
            START: { target: "requesting" },
          },
        },
      },
    });
    this.fsmSevice = interpret(this.stateMachine)
      .onTransition((state) => {
        this.state = state.value;
        this.onTransition(this.state);
      })
      .start();
    this.eventEmitter = new EventEmitter();
  }

  send(event) {
    this.fsmSevice.send(event);
  }
  onTransition() {}

  request = (context, event) =>
    new Promise((resolve, reject) => {
      let cmd = event.cmd;
      let options = event.params;
      options.responseType = "stream";
      const that = this;
      axios(options)
        .then(function (response) {

          response.data.on("data", function (chunk) {
            that.eventEmitter.emit(cmd, chunk.toString());
          });

          response.data.on("end", function () {
            console.log("Download completed");
            that.eventEmitter.emit(cmd, "end");
            that.send({ type: "CLOSE" });
          });
        })
        .catch(function (error) {
          console.log("【error】", error);
          that.send({ type: "ERROR" });
          return reject(error);
        });
      return resolve(event);
    });

  setError = (context, event) =>
    new Promise((resolve, reject) => {
      console.log("setError:", event.data);
      return resolve();
    });
}

module.exports.HttpChunkMachine = HttpChunkMachine;
