const { createMachine, interpret, actions } = require("xstate");
const EventEmitter = require("events");
const fs = require("fs");
const { readModel } = require("../../SDK/esSDK/readModel");
const { EsWorker } = require("../work/esWorker");
const esReadModel = new readModel();


class ESMachine {
  constructor() {
    this.stateMachine = createMachine({
      id: "args",
      initial: "disconnected",
      predictableActionArguments: true,
      states: {
        disconnected: {
          on: {
            START: { target: "connecting" },
          },
        },
        connecting: {
          invoke: {
            src: this.connecting,
            onDone: {
              target: "connected",
            },
            onError: {
              target: "error",
              actions: [this.setError],
            },
          },
        },
        connected: {
          on: {
            STOP: {
              target: "disconnected",
              actions: [this.closeConnection]
            },
            CLOSE: {
              target: "disconnected",
              actions: [this.closeConnection]
            },
          }
        },
        error: {
          on: {
            OPEN: { target: "connecting" },
          },
        },
      },
    });
    this.fsmSevice = interpret(this.stateMachine)
      .onTransition((state) => {
        this.state = state.value;
        this.onTransition(this.state);
      })
      .start();
    this.cmd = "start";
    this.eventEmitter = new EventEmitter();
    this.woker = new EsWorker();
    this.woker.on("event", (event) => {
      this.eventEmitter.emit(this.cmd, event);
    });
  }

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

  connecting = (context, event) =>
    new Promise(async (resolve, reject) => {
      let streamId = event.params.streamId;
      this.cmd = event.cmd;
      this.isClose = false;
      this.woker.subscribe({ streamId: streamId });
      return resolve(event);
    });

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


}


module.exports.ESMachine = ESMachine;
