/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

/* globals browser, module */

const replaceStringInRequest = (
  requestId,
  inString,
  outString,
  inEncoding = "utf-8"
) => {
  const filter = browser.webRequest.filterResponseData(requestId);
  const decoder = new TextDecoder(inEncoding);
  const encoder = new TextEncoder();
  const RE = new RegExp(inString, "g");
  const carryoverLength = inString.length;
  let carryover = "";

  filter.ondata = event => {
    const replaced = (
      carryover + decoder.decode(event.data, { stream: true })
    ).replace(RE, outString);
    filter.write(encoder.encode(replaced.slice(0, -carryoverLength)));
    carryover = replaced.slice(-carryoverLength);
  };

  filter.onstop = () => {
    if (carryover.length) {
      filter.write(encoder.encode(carryover));
    }
    filter.close();
  };
};

const CUSTOM_FUNCTIONS = {
  detectSwipeFix: injection => {
    const { urls, types } = injection.data;
    const listener = (injection.data.listener = ({ requestId }) => {
      replaceStringInRequest(
        requestId,
        "preventDefault:true",
        "preventDefault:false"
      );
      return {};
    });
    browser.webRequest.onBeforeRequest.addListener(listener, { urls, types }, [
      "blocking",
    ]);
  },
  detectSwipeFixDisable: injection => {
    const { listener } = injection.data;
    browser.webRequest.onBeforeRequest.removeListener(listener);
    delete injection.data.listener;
  },
  runScriptBeforeRequest: injection => {
    const { bug, message, request, script, types } = injection;
    const warning = `${message} See https://bugzilla.mozilla.org/show_bug.cgi?id=${bug} for details.`;

    const listener = (injection.listener = e => {
      const { tabId, frameId } = e;
      return browser.tabs
        .executeScript(tabId, {
          file: script,
          frameId,
          runAt: "document_start",
        })
        .then(() => {
          browser.tabs.executeScript(tabId, {
            code: `console.warn(${JSON.stringify(warning)})`,
            runAt: "document_start",
          });
        })
        .catch(_ => {});
    });

    browser.webRequest.onBeforeRequest.addListener(
      listener,
      { urls: request, types: types || ["script"] },
      ["blocking"]
    );
  },
  runScriptBeforeRequestDisable: injection => {
    const { listener } = injection;
    browser.webRequest.onBeforeRequest.removeListener(listener);
    delete injection.data.listener;
  },
};

module.exports = CUSTOM_FUNCTIONS;
