"use strict";

let eventsPath = null;
let port = null;
let currentVersionId = null;
let eventSource = null;

addEventListener("connect", (event) => {
  // Only keep one active port, for whichever tab was last loaded.
  if (port) {
    port.close();
  }
  port = event.ports[0];
  port.addEventListener("message", receiveMessage);
  port.start();
});

const receiveMessage = (event) => {
  if (event.data.type === "initialize") {
    const givenEventsPath = event.data.eventsPath;

    if (givenEventsPath !== eventsPath) {
      if (eventSource) {
        eventSource.close();
      }

      resetConnectTimeout();

      setTimeout(connectToEvents, 0);
    }

    eventsPath = event.data.eventsPath;
  }
};

let connectAttempts;
let connectTimeoutMs;

const resetConnectTimeout = () => {
  connectAttempts = 0;
  connectTimeoutMs = 100;
};
resetConnectTimeout();

const bumpConnectTimeout = () => {
  connectAttempts++;

  if (connectTimeoutMs === 100 && connectAttempts === 20) {
    connectAttempts = 0;
    connectTimeoutMs = 300;
  } else if (connectTimeoutMs === 300 && connectAttempts === 20) {
    connectAttempts = 0;
    connectTimeoutMs = 1000;
  } else if (connectTimeoutMs === 1000 && connectAttempts === 20) {
    connectAttempts = 0;
    connectTimeoutMs = 3000;
  } else if (connectAttempts === 100) {
    // Give up after 5 minutes.
    console.debug(
      "😢 django-browser-reload failed to connect after 5 minutes, shutting down."
    );
    close();
    return;
  }
  if (connectAttempts === 0) {
    console.debug(
      "😅 django-browser-reload EventSource error, retrying every " +
        connectTimeoutMs +
        "ms"
    );
  }
};

const connectToEvents = () => {
  if (!eventsPath) {
    setTimeout(connectToEvents, connectTimeoutMs);
    return;
  }

  eventSource = new EventSource(eventsPath);

  eventSource.addEventListener("open", () => {
    console.debug("😎 django-browser-reload connected");
  });

  eventSource.addEventListener("message", (event) => {
    // Reset connection timeout when receiving a message, as it’s proof that
    // we are actually connected.
    resetConnectTimeout();

    const message = JSON.parse(event.data);

    if (message.type === "ping") {
      if (currentVersionId !== null && currentVersionId !== message.versionId) {
        console.debug("🔁 django-browser-reload triggering reload.");
        port.postMessage("Reload");
      }

      currentVersionId = message.versionId;
    } else if (message.type === "reload") {
      port.postMessage("Reload");
    }
  });

  eventSource.addEventListener("error", () => {
    eventSource.close();
    eventSource = null;
    bumpConnectTimeout();
    setTimeout(connectToEvents, connectTimeoutMs);
  });
};
