/* global chrome, pako */

function log(...args) {
  console.log.apply(null, ["[webrtc-internal-exporter:background]", ...args]);
}

log("loaded");

import "./assets/pako.min.js";

const DEFAULT_OPTIONS = {
  url: process.env.WEBRTC_INTERNALS_EXPORTER_URL + ":9092",
  username: "",
  password: "",
  updateInterval: 2,
  gzip: false,
  job: "webrtc-internals-exporter",
  enabledOrigins: {},
  enabledStats: ["data-channel", "local-candidate", "remote-candidate", "candidate-pair"]
};

const options = {};

// Handle install/update.
chrome.runtime.onInstalled.addListener(async ({ reason }) => {
  log("onInstalled", reason);
  if (reason === "install") {
    await chrome.storage.sync.set(DEFAULT_OPTIONS);
  } else if (reason === "update") {
    const options = await chrome.storage.sync.get();
    await chrome.storage.sync.set({
      ...DEFAULT_OPTIONS,
      ...options,
    });
  }
});

async function updateTabInfo(tab) {
  const tabId = tab.id;
  const origin = new URL(tab.url || tab.pendingUrl).origin;

  if (options.enabledOrigins) {
    const { peerConnectionsPerOrigin } = await chrome.storage.local.get(
      "peerConnectionsPerOrigin",
    );
    const peerConnections =
      (peerConnectionsPerOrigin && peerConnectionsPerOrigin[origin]) || 0;

    chrome.action.setTitle({
      title: `WebRTC Internals Exporter\nActive Peer Connections: ${peerConnections}`,
      tabId,
    });
    chrome.action.setBadgeText({ text: `${peerConnections}`, tabId });
    chrome.action.setBadgeBackgroundColor({ color: "rgb(63, 81, 181)", tabId });
  } else {
    chrome.action.setTitle({
      title: `WebRTC Internals Exporter (disabled)`,
      tabId,
    });
    chrome.action.setBadgeText({ text: "", tabId });
  }
}

async function optionsUpdated() {
  const [tab] = await chrome.tabs.query({
    active: true,
    lastFocusedWindow: true,
  });
  await updateTabInfo(tab);
}

chrome.storage.sync.get().then((ret) => {
  Object.assign(options, ret);
  log("options loaded");
  optionsUpdated();
});

chrome.storage.onChanged.addListener((changes, areaName) => {
  if (areaName !== "sync") return;

  for (let [key, { newValue }] of Object.entries(changes)) {
    options[key] = newValue;
  }
  log("options changed");
  optionsUpdated();
});

chrome.tabs.onActivated.addListener(async ({ tabId }) => {
  try {
    const tab = await chrome.tabs.get(tabId);
    await updateTabInfo(tab);
  } catch (err) {
    log(`get tab error: ${err.message}`);
  }
});

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo) => {
  if (!changeInfo.url) return;
  await updateTabInfo({ id: tabId, url: changeInfo.url });
});

// Send data to POST handler.
async function sendJsonData(method, data) {
  const { url, username, password, gzip, job } = options;
  const headers = {
    "Content-Type": "application/json",
  };
  if (username && password) {
    headers.Authorization = "Basic " + btoa(`${username}:${password}`);
  }
  if (data && gzip) {
    headers["Content-Encoding"] = "gzip";
    data = await pako.gzip(data);
  }
  log(`sendJsonData: ${data} \n ${data.length} bytes (gzip: ${gzip}) url: ${url} job: ${job}`);
  const start = Date.now();
  const response = await fetch(
    `${url}/${job}`,
    {
      method,
      headers,
      body: method === "POST" ? data : undefined,
    },
  );

  const stats = await chrome.storage.local.get([
    "messagesSent",
    "bytesSent",
    "totalTime",
    "errors",
  ]);
  if (data) {
    stats.messagesSent = (stats.messagesSent || 0) + 1;
    stats.bytesSent = (stats.bytesSent || 0) + data.length;
    stats.totalTime = (stats.totalTime || 0) + Date.now() - start;
  }
  if (!response.ok) {
    stats.errors = (stats.errors || 0) + 1;
  }
  await chrome.storage.local.set(stats);

  if (!response.ok) {
    const text = await response.text();
    throw new Error(`Response status: ${response.status} error: ${text}`);
  }

  return response.text();
}

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.event === "peer-connection-stats") {

    sendJsonData("POST", JSON.stringify(message.data))
      .then(() => {
        sendResponse({});
      })
      .catch((err) => {
        sendResponse({ error: err.message });
      });
  } else if (message.event === "peer-connections-stats") {
    
    sendJsonData("POST", JSON.stringify(message.data))
      .then(() => {
        sendResponse({});
      })
      .catch((err) => {
        sendResponse({ error: err.message });
      });
  } else {
    sendResponse({ error: "unknown event" });
  }

  return true;
});
