#  _________________________________________________________________________
#
#  PyUtilib: A Python utility library.
#  Copyright (c) 2008 Sandia Corporation.
#  This software is distributed under the BSD License.
#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
#  the U.S. Government retains certain rights in this software.
#  _________________________________________________________________________

"""A plugin that manages temporary files."""

__all__ = ['ITempfileManager', 'TempfileManagerPlugin', 'TempfileManager']

import sys
import os
import tempfile

from pyutilib.component.config.options import *
from pyutilib.component.config.managed_plugin import *


class ITempfileManager(Interface):
    """Interface for managing temporary files."""

    def create_tempfile(self, suffix=None, prefix=None, text=False, dir=None):
        """Return the absolute path of a temporary filename that is guaranteed to be unique."""

    def add_tempfile(self, filename):
        """Declare this file to be temporary."""

    def clear_tempfiles(self, remove=True):
        """Delete all temporary files."""

    def sequential_files(self, ctr=0):
        """Start generating sequential files, using the specified counter"""

    def unique_files(self):
        """Start generating unique files"""

    def push(self):
        """Push tempfiles onto a stack.  This creates a new context for tempfiles."""

    def pop(self, remove=True):
        """Pop tempfiles onto a stack.  Tempfiles that are popped off the stack are deleted."""


class TempfileManagerPlugin(ManagedSingletonPlugin):
    """A plugin that manages temporary files."""

    implements(ITempfileManager)

    def __init__(self, **kwds):
        kwds['name']='TempfileManager'
        ManagedSingletonPlugin.__init__(self,**kwds)
        self._tempfiles = [[]]
        declare_option("tempdir", default=None)
        self._ctr=-1

    def create_tempfile(self, suffix=None, prefix=None, text=False, dir=None):
        """
        Return the absolute path of a temporary filename that is
        guaranteed to be unique.  This function generates the file and returns
        the filename.
        """
        if suffix is None:
            suffix=''
        if prefix is None:
            prefix='tmp'
        if dir is None:
            dir=self.tempdir
        if self._ctr >= 0:
            fname = os.path.join(dir,prefix+str(self._ctr)+suffix)
            self._ctr += 1
        else:
            ans = tempfile.mkstemp(suffix=suffix, prefix=prefix, text=text, dir=dir)
            ans = list(ans)
            if not os.path.isabs(ans[1]):           #pragma:nocover
                fname = os.path.join(dir,ans[1])
            else:
                fname = ans[1]
            os.close(ans[0])
        self._tempfiles[-1].append(fname)
        if os.path.exists(fname):
            os.remove(fname)
        return fname

    def add_tempfile(self, filename, exists=True):
        """Declare this file to be temporary."""
        tmp = os.path.abspath(filename)
        if exists and not os.path.exists(tmp):
            raise IOError("Temporary file does not exist: "+tmp)
        self._tempfiles[-1].append(tmp)

    def clear_tempfiles(self, remove=True):
        """Delete all temporary files."""
        while len(self._tempfiles) > 1:
            self.pop(remove)
        self.pop(remove)

    def sequential_files(self, ctr=0):
        """Start generating sequential files, using the specified counter"""
        self._ctr=ctr

    def unique_files(self):
        """Stop generating sequential files, using the specified counter"""
        self._ctr=-1

    def push(self):
        self._tempfiles.append([])

    def pop(self, remove=True):
        files = self._tempfiles.pop()
        if remove:
            for file in files:
                if os.path.exists(file):
                    os.remove(file)
        if len(self._tempfiles) == 0:
            self._tempfiles = [[]]

#
# This global class provides a convenient handle to this
# singleton plugin
#
TempfileManager = TempfileManagerPlugin()
