text: #!/usr/bin/env yarn node
  
  process.env["DEBUG"] = "tinyburg:struct-loader";
  process.env["LOG_DEST"] = "./checkSaveDataTypes.log";
  
  require("colors");
  const fs = require("fs");
  const diff = require("diff");
  const Pino = require("pino");
  const ttconfig = require("../tinyburgrc.json");
  const tinyburg = require("../dist/tinyburg").fromConfig(ttconfig);
  
  (async function main() {
      // Clear log file before starting
      try {
          fs.unlinkSync(process.env.LOG_DEST);
          // eslint-disable-next-line no-empty
      } catch (err) {}
  
      // Determine what version the server is currently using
      const saveData = await tinyburg.downloadSave();
      const saveDataJson = await tinyburg.parseSaveToJson(saveData);
      const saveVersion = saveDataJson.ver;
      console.log("Current Nimblebit saveData version is: %s\n", saveVersion);
  
      // Flush the logger after parsing the save data so that everything buffered will
      // be committed to the file and we can read it next
      const finalLogger = Pino.pino.final(tinyburg.logger.log);
      finalLogger.info("Goodbye");
  
      // Read and parse the log file
      let log = fs.readFileSync(process.env.LOG_DEST, "utf8");
      let lines = log.split("\n");
      lines.pop();
      lines = lines
          .map((line) => JSON.parse(line))
          .filter((line) => line.namespace === "save-parser" || line.namespace === "parsing-subroutines")
          .map((line) => line.msg)
          .filter((msg) => /Save does not have block/.test(msg))
          .map((msg) => msg + ", This block does not appear to be used in this version (or maybe this save does not have any data for it)");
  
      // Log the blocks that produced errors
      console.log(lines);
  
      // Find any blocks that could be written/defined better
      Object.values(saveDataJson).forEach((value, index) => {
          if (typeof value === "string") {
              if (value.includes("|") || value.includes(",") || (value.includes("[") && value.includes("]"))) {
                  console.log(`Block ${Object.keys(saveDataJson)[index]} could be better represented`);
              }
          }
      });
  
      // We are going to look for any blocks that are present when downloading, but are not there
      // anymore after we have repackaged the save data. This means that somewhere, our saveParser
      // mishandled this block and we should probably go back and examine its implementation
      const saveDataRepackaged = await tinyburg.concatJsonToBlock(saveDataJson);
      console.log(
          "\nBelow highlights how saveData might be mal-interpreted when parsing to and from json. Consider fixing any errors with this version (red means the text was deleted after going from saveData->json->saveData, greens means it was inserted, gray means no change - we want all gray)"
      );
      let differences = diff.diffChars(saveData.toString(), saveDataRepackaged.toString());
  
      differences.forEach((part) => {
          // green for additions, red for deletions grey for common parts
          const color = part.added ? "green" : part.removed ? "red" : "grey";
          process.stderr.write(part.value[color]);
      });
      console.log();
  })();
  