# Copyright 2013 The Emscripten Authors.  All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License.  Both these licenses can be
# found in the LICENSE file.

import os
import shutil
import tempfile
import atexit
import stat
import sys


# Attempts to delete given possibly nonexisting or read-only directory tree or filename.
# If any failures occur, the function silently returns without throwing an error.
def try_delete(pathname):
  try:
    os.unlink(pathname)
  except OSError:
    pass
  if not os.path.exists(pathname):
    return
  try:
    shutil.rmtree(pathname, ignore_errors=True)
  except IOError:
    pass
  if not os.path.exists(pathname):
    return

  write_bits = stat.S_IWRITE | stat.S_IWGRP | stat.S_IWOTH

  def is_writable(path):
    return (os.stat(path).st_mode & write_bits) == write_bits

  def make_writable(path):
    os.chmod(path, os.stat(path).st_mode | write_bits)

  # Some tests make files and subdirectories read-only, so rmtree/unlink will not delete
  # them. Force-make everything writable in the subdirectory to make it
  # removable and re-attempt.
  if not is_writable(pathname):
    make_writable(pathname)

  if os.path.isdir(pathname):
    for directory, subdirs, files in os.walk(pathname):
      for item in files + subdirs:
        i = os.path.join(directory, item)
        make_writable(i)

  try:
    shutil.rmtree(pathname, ignore_errors=True)
  except IOError:
    pass


class TempFiles(object):
  def __init__(self, tmp, save_debug_files=False):
    self.tmp = tmp
    self.save_debug_files = save_debug_files
    self.to_clean = []

    atexit.register(self.clean)

  def note(self, filename):
    self.to_clean.append(filename)

  def get(self, suffix):
    """Returns a named temp file with the given prefix."""
    named_file = tempfile.NamedTemporaryFile(dir=self.tmp, suffix=suffix, delete=False)
    self.note(named_file.name)
    return named_file

  def get_file(self, suffix):
    """Returns an object representing a RAII-like access to a temp file, that has convenient pythonesque
    semantics for being used via a construct 'with TempFiles.get_file(..) as filename:'. The file will be
    deleted immediately once the 'with' block is exited."""
    class TempFileObject(object):
      def __enter__(self_):
        self_.file = tempfile.NamedTemporaryFile(dir=self.tmp, suffix=suffix, delete=False)
        self_.file.close() # NamedTemporaryFile passes out open file handles, but callers prefer filenames (and open their own handles manually if needed)
        return self_.file.name

      def __exit__(self_, type, value, traceback):
        if not self.save_debug_files:
          try_delete(self_.file.name)
    return TempFileObject()

  def get_dir(self):
    """Returns a named temp directory with the given prefix."""
    directory = tempfile.mkdtemp(dir=self.tmp)
    self.note(directory)
    return directory

  def clean(self):
    if self.save_debug_files:
      print('not cleaning up temp files since in debug-save mode, see them in %s' % (self.tmp,), file=sys.stderr)
      return
    for filename in self.to_clean:
      try_delete(filename)
    self.to_clean = []

  def run_and_clean(self, func):
    try:
      return func()
    finally:
      self.clean()
