const fs = require("fs");

function writeToFile(i, { component, content }) {
  try {
    fs.writeFileSync(`sirs-data-${i}-${component.toLowerCase()}.dat`, content);
    // file written successfully
  } catch (err) {
    // eslint-disable-next-line no-console
    console.error(err);
  }
}
function saveFiles(i, { t, S, I, R }) {
  let contentS = "x y\n";
  let contentI = "x y\n";
  let contentR = "x y\n";

  for (let j = 0; j < t.length; j++) {
    contentS += `${t[j]} ${S[j]}\n`;
    contentI += `${t[j]} ${I[j]}\n`;
    contentR += `${t[j]} ${R[j]}\n`;
  }

  writeToFile(i, { component: "s", content: contentS });
  writeToFile(i, { component: "i", content: contentI });
  writeToFile(i, { component: "r", content: contentR });
}

function computeAndSaveToFile(i, item) {
  const {
    totalPop,
    initialInfectedPop,
    maxTime,
    timeTick,
    beta,
    alpha,
    susceptibility
  } = item;

  const IArr = [];
  const SArr = [];
  const RArr = [];
  const tArr = [];

  let S = totalPop;
  let I = initialInfectedPop;
  let R = 0;

  for (let t = 0; t <= maxTime; t += timeTick) {
    const nowInfected = beta * S * (I / totalPop);
    const nowSusceptible = susceptibility * R;
    const nowRecovered = alpha * I;

    const delS = -nowInfected + nowSusceptible;
    const delI = nowInfected - nowRecovered;
    const delR = nowRecovered - nowSusceptible;

    S += delS * timeTick;
    I += delI * timeTick;
    R += delR * timeTick;

    IArr.push(I);
    SArr.push(S);
    RArr.push(R);
    tArr.push(Number(t.toFixed(2)));
  }

  saveFiles(i, { t: tArr, S: SArr, I: IArr, R: RArr });
}

// SIRS MODEL GENERATOR

/*
 * timeTick: the time duration of each tick
 * maxTime: the maximum time for which the model will run
 * totalPop: the total population
 * initialInfectedPop: the initial infected population
 * beta: the rate of infection
 * alpha: the rate of recovery
 * susceptibility: the rate in which agents become susceptible. if zero, then the model is SIR
 */
const data = [
  {
    timeTick: 0.1,
    maxTime: 20,
    totalPop: 100000,
    initialInfectedPop: 1,
    beta: 3,
    alpha: 1,
    susceptibility: 1
  },
  {
    timeTick: 0.1,
    maxTime: 20,
    totalPop: 100000,
    initialInfectedPop: 1,
    beta: 1.5,
    alpha: 0.5,
    susceptibility: 1
  },
  {
    timeTick: 0.1,
    maxTime: 20,
    totalPop: 100000,
    initialInfectedPop: 1,
    beta: 10,
    alpha: 5,
    susceptibility: 0.5
  }
];

for (let i = 0; i < data.length; i++) {
  const { timeTick, initialInfectedPop, totalPop } = data[i];

  // basic error handling
  if (timeTick <= 0) {
    throw new Error("Time tick must be greater than zero");
  }
  if (initialInfectedPop > totalPop) {
    throw new Error(
      "Infected population cannot be larger than the total population"
    );
  }

  computeAndSaveToFile(i + 1, data[i]);
}