console.log("=================================================");
console.log(" Xuda UI Worker started..." + new Date().getTime());
console.log("=================================================");

var UI_WORKER_OBJ = { jobs: [], num: 9000 };

const init_queue = async function () {
  let last_job_in_queue = 0;
  const job_iterator = async function () {
    let from_job_num_to_run = last_job_in_queue;
    last_job_in_queue = UI_WORKER_OBJ.num - from_job_num_to_run;

    if (
      typeof UI_WORKER_OBJ.stat === "undefined" ||
      UI_WORKER_OBJ.stat === "undefined" ||
      UI_WORKER_OBJ.stat === null
    ) {
      // idle
      this.attempt = 0;
      if (UI_WORKER_OBJ.jobs.length) {
        // clearInterval(this._interval);
        for await (const [key, val] of Object.entries(UI_WORKER_OBJ.jobs)) {
          if (val.job_num < from_job_num_to_run) continue;

          if (val.stat) {
            break;
          }

          if (!UI_WORKER_OBJ.jobs[Number(key)] || val.job_num === 9999999)
            continue;

          // if (val.dsSessionP && !_session.DS_GLB[val.dsSessionP]) {
          //   delete_job(val.job_num);
          //   continue;
          // }
          await execute(val);
        }
      }
    } else {
      //busy

      this.attempt++;
    }
  };
  let interval = setInterval(job_iterator, 1);
};
const add_to_queue = async function (params) {
  var obj = ({
    SESSION_ID,
    source,
    functionP,
    paramsP,
    calling_job,
    xu_ui_id,
    dsSession,
    calling_trigger_prop,
    job_num: UI_WORKER_OBJ.num,
  } = params);

  if (functionP === "execute_xu_all_attributes") {
    const queue_key =
      source +
      "_" +
      functionP +
      "_" +
      (xu_ui_id || "") +
      "_" +
      (paramsP?.fields_arr?.toString() || "");

    obj.queue_key = queue_key;

    let exist_job = UI_WORKER_OBJ.jobs.find((e) => {
      if (e.queue_key === queue_key) {
        return e;
      }
    });

    if (exist_job) {
      exist_job.paramsP = paramsP;
      exist_job.calling_trigger_prop = calling_trigger_prop;

      return;
    }
  }
  if (calling_job) {
    var job_index = find_job_index(calling_job);

    if (job_index === null || typeof job_index === "undefined") return;

    try {
      if (!UI_WORKER_OBJ.jobs[job_index].splice_count) {
        UI_WORKER_OBJ.jobs[job_index].splice_count = 0;
      }
      UI_WORKER_OBJ.jobs[job_index].splice_count++;
      UI_WORKER_OBJ.jobs.splice(
        job_index + UI_WORKER_OBJ.jobs[job_index].splice_count,
        0,
        obj
      );
      // }
    } catch (e) {
      console.error("bug");
    }
  } else {
    UI_WORKER_OBJ.jobs.push(obj);
  }

  UI_WORKER_OBJ.num++;
  return UI_WORKER_OBJ.num - 1;
};
const delete_job = async function (jobNoP) {
  var job_index = find_job_index(jobNoP);

  if (!UI_WORKER_OBJ.jobs[job_index]) {
    UI_WORKER_OBJ.stat = null;
    return;
  }

  var dsSession = UI_WORKER_OBJ.jobs[job_index].dsSession;

  //   TBD

  //   if (
  //     dsSession &&
  //     ds_obj?.loops_limit &&
  //     ds_obj?.loops_count < ds_obj?.loops_limit - 1
  //   ) {
  //     return;
  //   }
  UI_WORKER_OBJ.stat = null;

  UI_WORKER_OBJ.jobs.splice(job_index, 1);
};

const find_job_index = function (jobNoP) {
  var ret = null;
  if (!UI_WORKER_OBJ) return ret;
  for (let [key, val] of Object.entries(UI_WORKER_OBJ.jobs)) {
    if (val && val.job_num == jobNoP) {
      ret = Number(key);
      break;
    }
  }
  return ret;
};

const execute = async function (queue_obj) {
  try {
    var job_index = find_job_index(queue_obj.job_num);
    if (UI_WORKER_OBJ.jobs?.[job_index]?.stat === "busy") {
      if (queue_obj.jobNoP) UI_WORKER_OBJ.stat = job_index;
      return;
    }
    if (queue_obj.jobNoP && !UI_WORKER_OBJ.jobs[job_index]) {
      UI_WORKER_OBJ.stat = null;
      return;
    }

    if (queue_obj.jobNoP) UI_WORKER_OBJ.stat = job_index;
    if (UI_WORKER_OBJ.jobs[job_index]) {
      UI_WORKER_OBJ.jobs[job_index].stat = "busy";
    }

    postMessage(queue_obj);
  } catch (error) {
    debugger;
  }
};

self.addEventListener(
  "message",
  async function (e) {
    switch (e.data.method) {
      case "init": {
        init_queue();
        break;
      }

      case "add_to_queue": {
        add_to_queue(e.data.params);
        break;
      }

      case "delete_job": {
        delete_job(e.data.params.job_num);
        break;
      }

      default:
        break;
    }
  },
  false
);
