System.register(["./files.js", "utils"], function (_export, _context) {
  "use strict";

  var Files, uniq;
  return {
    setters: [function (_filesJs) {
      Files = _filesJs.default;
    }, function (_utils) {
      uniq = _utils.uniq;
    }],
    execute: function () {
      const __SystemJSRewritingHack = {};
      _recorder_._src_client_files_caches_js = _recorder_._src_client_files_caches_js || {};
      Object.defineProperty(_recorder_._src_client_files_caches_js, "ensureBootlistOptionsFiles", {
        get() {
          return ensureBootlistOptionsFiles;
        },

        set(thisIsVererySecretVariableName) {
          _export("ensureBootlistOptionsFiles", ensureBootlistOptionsFiles = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "invalidateOptionsFiles", {
        get() {
          return invalidateOptionsFiles;
        },

        set(thisIsVererySecretVariableName) {
          _export("invalidateOptionsFiles", invalidateOptionsFiles = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "invalidateTranspiledFiles", {
        get() {
          return invalidateTranspiledFiles;
        },

        set(thisIsVererySecretVariableName) {
          _export("invalidateTranspiledFiles", invalidateTranspiledFiles = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "defaultFileList", {
        get() {
          return defaultFileList;
        },

        set(thisIsVererySecretVariableName) {
          defaultFileList = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "purgeTranspiledFiles", {
        get() {
          return purgeTranspiledFiles;
        },

        set(thisIsVererySecretVariableName) {
          _export("purgeTranspiledFiles", purgeTranspiledFiles = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "updateCachedFilesList", {
        get() {
          return updateCachedFilesList;
        },

        set(thisIsVererySecretVariableName) {
          _export("updateCachedFilesList", updateCachedFilesList = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_files_caches_js, "Files", {
        get() {
          return Files;
        },

        set(thisIsVererySecretVariableName) {
          Files = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });


      self.lively4fetchLog = self.lively4fetchLog || [];

      Object.defineProperty(_recorder_._src_client_files_caches_js, "uniq", {
        get() {
          return uniq;
        },

        set(thisIsVererySecretVariableName) {
          uniq = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });


      // _.uniq(that.value.split("\n")).join("\n")
      async function updateCachedFilesList() {
        var _context2;

        var oldlist = (await fetch(lively4url + "/.lively4bootfilelist").then(r => r.text())).split("\n");

        var newlist = Array.from(self.lively4fetchLog.filter(ea => ea.method == "GET")).map(ea => ea.url).filter(ea => ea.startsWith(lively4url)).filter(ea => !ea.match("lively4bundle.zip")).map(ea => ea.replace(lively4url + "/", ""));

        var list = (_context2 = newlist.concat(oldlist), uniq).call(_context2).sort();

        await fetch(lively4url + "/.lively4bootfilelist", {
          method: "PUT",
          body: list.join("\n"
          //JSON.stringify(list).replace(/",/g,'",\n') // just a bit pretty print
          ) });
        return list;
      }

      _export("updateCachedFilesList", updateCachedFilesList);

      async function purgeTranspiledFiles() {
        var transpiledFiles = await Files.walkDir(lively4url + "/.transpiled/");
        var log = "";
        for (var eaURL of transpiledFiles) {
          log += await fetch(eaURL, { method: "DELETE" });
        }
        // should we make it live?
        return transpiledFiles.map(ea => ea.replace(lively4url + "/.transpiled/", ""));
      }

      _export("purgeTranspiledFiles", purgeTranspiledFiles);

      function defaultFileList() {
        return fetch(lively4url + "/", {
          method: "OPTIONS",
          headers: {
            filelist: true
          }
        }).then(r => r.json());
      }

      async function invalidateTranspiledFiles(files) {
        files = files || (await defaultFileList());

        var log = "";
        var map = new Map(); // make file lookup faster
        for (let file of files.contents) {
          let path = file.name.replace(/^\.\//, "");
          if (path.match(/^\.transpiled\//)) {
            map.set(path, file);
          }
        }
        for (let file of files.contents) {
          var path = file.name.replace(/^\.\//, "");
          if (path.match(/\.js$/)) {
            var transpiledPath = ".transpiled/" + path.replace(/\//g, "_");
            var transpiled = map.get(transpiledPath);
            if (transpiled) {
              if (file.modified > transpiled.modified) {
                var jsURL = lively4url + "/" + transpiledPath;
                var mapURL = lively4url + "/" + transpiledPath + ".map.json";
                log += "delete " + jsURL + "\n";
                log += "delete " + mapURL + "\n";
                fetch(jsURL, { method: "DELETE" });
                fetch(mapURL, { method: "DELETE" });
              }
            }
          }
        }
        return log;
      }

      _export("invalidateTranspiledFiles", invalidateTranspiledFiles);

      async function invalidateOptionsFiles(files) {
        files = files || (await defaultFileList());

        var log = "";
        var map = new Map(); // make file lookup faster
        for (let file of files.contents) {
          let path = file.name.replace(/^\.\//, "");
          if (path.match(/^\.options\//)) {
            map.set(path, file);
          }
        }
        for (let file of files.contents) {
          var path = file.name.replace(/^\.\//, "");
          var optionsPath = ".options/" + path.replace(/\//g, "_");
          var opotionsFile = map.get(optionsPath);
          if (opotionsFile) {
            if (file.modified > opotionsFile.modified) {
              var optionsURL = lively4url + "/" + optionsPath;
              log += "delete " + optionsURL + "\n";
              fetch(optionsURL, { method: "DELETE" });
            }
          }
        }
        return log;
      }

      _export("invalidateOptionsFiles", invalidateOptionsFiles);

      async function ensureBootlistOptionsFiles() {
        var bootfiles = (await fetch(lively4url + "/" + ".lively4bootfilelist").then(r => r.text())).split("\n");
        for (var ea of bootfiles) {
          var optionsContents = await fetch(ea, {
            method: "OPTIONS"
          }).then(r => r.text());

          var optionsURL = lively4url + "/.options/" + ea.replace(/\//g, "_");
          await fetch(optionsURL, {
            method: "PUT",
            body: optionsContents,
            headers: {
              nocommit: true
            }
          });
          console.log("[files-caches] ensureBootlistOptionsFiles: updated " + ea);
        }
      }

      // updateCachedFilesList()


      _export("ensureBootlistOptionsFiles", ensureBootlistOptionsFiles);

      if (!navigator.serviceWorker) {
        console.warn("[files]... could not register message handler with no-existing service worker");
      } else {
        lively.removeEventListener("files", navigator.serviceWorker);
        lively.addEventListener("files", navigator.serviceWorker, "message", async evt => {
          try {
            if (evt.data.name == 'swx:fech:request') {
              var map = Files.cachedFileMap();
              console.log("[files] fetch request: " + evt.data.method + " " + evt.data.url);
              self.lively4fetchLog.push({
                time: performance.now(),
                method: evt.data.method,
                url: evt.data.url
              });
            }
          } catch (err) {
            console.error("[files] error during swx message handling...", err);
          }
        });
      }
    }
  };
});