text: import io
  import json
  from defang import defang
  
  class MachinaeOutput:
      @staticmethod
      #pylint: disable=no-else-return, redefined-builtin, inconsistent-return-statements
      #Will be cleaned up in upcoming refactor
      def get_formatter(format):
          if format.upper() == "N":
              return NormalOutput()
          elif format.upper() == "J":
              return JsonOutput()
          elif format.upper() == "D":
              return DotEscapedOutput()
          elif format.upper() == "S":
              return ShortOutput()
  
      @staticmethod
      def escape(text):
          return str(text)
  
      #pylint: disable=attribute-defined-outside-init
      #Will be cleaned up in upcoming refactor
      def init_buffer(self):
          self._buffer = io.StringIO()
  
      def print(self, line, lf=True):
          self._buffer.write(line)
          if lf:
              self._buffer.write("\n")
  
  
  class NormalOutput(MachinaeOutput):
      def output_header(self, target, otype, otype_detected):
          self.print("*" * 80)
          self.print("* Information for {0}".format(self.escape(target)))
          self.print("* Observable type: {0} (Auto-detected: {1})".format(otype, otype_detected))
          self.print("*" * 80)
          #This needs to be refactored so the site from args is available here. No time currently, will do though
          self.print("Not seeing what you expect? Likely not a valid site. Try running with --list-sites")
  
      def run(self, result_sets: object):
          self.init_buffer()
          #pylint: disable=too-many-nested-blocks
          for row in result_sets:
              (target, otype, otype_detected) = row.target_info
  
              self.output_header(target, otype, otype_detected)
              self.print("")
  
              for item in row.results:
                  site = item.site_info
                  if hasattr(item, "error_info"):
                      self.print("[!] Error from {0}: {1}".format(site["name"], item.error_info))
                      continue
  
                  if not item.resultset:
                      self.print("[-] No {0} Results".format(site["name"]))
                  else:
                      self.print("[+] {0} Results".format(site["name"]))
                      for result in item.resultset:
                          labels = getattr(result[0], "labels", None)
                          if len(result[0].values()) > 1 or labels is not None:
                              values = map(repr, result[0].values())
                              values = map(self.escape, values)
                              if labels is not None:
                                  values = zip(labels, values)
                                  values = ["{0}: {1}".format(label, value) for (label, value) in values]
                                  output = ", ".join(values)
  
                              if result[1] is not None:
                                  output = "({0})".format(", ".join(values))
                                  output = defang(output)
                          else:
                              output = self.escape(list(result[0].values())[0])
                              output = defang(output)
                          if result[1] is not None:
                              output = "{1}: {0}".format(output, result[1])
                              output = defang(output)
                          self.print("    [-] {0}".format(output))
  
          return self._buffer.getvalue()
  
  
  class DotEscapedOutput(NormalOutput):
      escapes = {
          # ".": "\u2024",
          # ".": "<dot>",
          # ".": " DOT ",
          ".": "[.]",
          "@": " AT ",
          "http://": "hxxp://",
          "https://": "hxxps://",
      }
  
      def output_header(self, target, otype, otype_detected):
          super().output_header(target, otype, otype_detected)
          self.print("* These characters are escaped in the output below:")
          for (find, replace) in self.escapes.items():
              self.print("* '{0}' replaced with '{1}'".format(find, replace))
          self.print("* Do not click any links you find below")
          self.print("*" * 80)
  
      @classmethod
      def escape(cls, text):
          text = super(DotEscapedOutput, cls).escape(text)
          for (find, replace) in cls.escapes.items():
              text = text.replace(find, replace)
          return text
  
  #pylint: disable=no-self-use, unused-variable
  #Will be cleaned up in upcoming refactor
  class JsonGenerator(MachinaeOutput):
      def run(self, result_sets):
          records = list()
          for row in result_sets:
              (target, otype, otype_detected) = row.target_info
  
              for item in row.results:
                  output = dict()
                  output["site"] = item.site_info["name"]
                  output["results"] = dict()
                  output["observable"] = target
                  output["observable type"] = otype
                  output["observable type detected"] = otype_detected
  
                  if hasattr(item, "error_info"):
                      output["results"] = {"error_info": str(item.error_info)}
                  elif item.resultset:
                      for result in item.resultset:
                          if result.pretty_name not in output["results"]:
                              output["results"][result.pretty_name] = list()
                          values = list(result.value.values())
                          if len(values) == 1:
                              output["results"][result.pretty_name].append(values[0])
                          elif len(values) > 1:
                              output["results"][result.pretty_name].append(values)
                      for (k, v) in output["results"].items():
                          if len(v) == 1:
                              output["results"][k] = v[0]
                  records.append(output)
          return records
  
  
  class JsonOutput(JsonGenerator):
      def run(self, result_sets):
          self.init_buffer()
  
          for record in super().run(result_sets):
              self.print(json.dumps(record))
  
          return self._buffer.getvalue()
  
  
  class ShortOutput(MachinaeOutput):
      def run(self, result_sets):
          self.init_buffer()
  
          for row in result_sets:
              (target, otype, otype_detected) = row.target_info
              self.print("[+] {0}".format(target))
  
              for item in row.results:
                  site = item.site_info
                  if hasattr(item, "error_info"):
                      self.print("    {0}: Error".format(site["name"]))
                  elif not item.resultset:
                      self.print("    {0}: No".format(site["name"]))
                  else:
                      self.print("    {0}: Yes".format(site["name"]))
  
          return self._buffer.getvalue()
  