import fnmatch
import os
import shutil
import tempfile

import dirutil
from buffer import Buffer

ignore = ['*.o', '*.lo', '*.la', '#*#', '*.rej', '*~', '.#*', '.DS_Store',
          '*.pyc', '*.pyo', '.sconsign.dblite']

class DirBuffer(Buffer):
    btype = 'dir'
    def __init__(self, path, name=None):
        Buffer.__init__(self)
        self.path = os.path.realpath(path)

        self.settings['hide-dot']  = True
        self.settings['type-sort'] = False
        self.settings['hide-glob'] = True
        self.settings['ignores']   = list(ignore)

    def changed(self):
        return False
    def readonly(self):
        return True
    def name(self):
        return self.path
    def path_exists(self):
        return os.path.exists(self.path)

    def get_names(self):
        if not self.path_exists():
            raise Exception, "directory %r does not exists" % self.path
        names = os.listdir(self.path)
        if self.path != '/':
            names.insert(0, '..')
        names.insert(0, '.')
        return names
    def _make_path(self, name):
        return os.path.join(self.path, name)
    def _get_lines(self):
        names = self.get_names()

        fieldlines = []
        maxlens = [0] * 5
        for name in names:
            if self.settings.get('hide-dot'):
                if name.startswith('.') and name not in ('.', '..'):
                    continue
            if self.settings.get('hide-glob'):
                skip = False
                for glob in self.settings.get('ignores', []):
                    if fnmatch.fnmatch(name, glob):
                        skip = True
                        break
                if skip:
                    continue
            path = self._make_path(name)
            fields = dirutil.path_fields(path, name)
            for i in xrange(0, 5):
                try:
                    maxlens[i] = max(maxlens[i], len(fields[i]))
                except:
                    raise Exception, '%d %r' % (i, fields[i])
            fieldlines.append(fields)

        if self.settings.get('type-sort'):
            fieldlines.sort(cmp=dirutil.path_sort)
        else:
            fieldlines.sort(cmp=dirutil.path_sort2)
        fmt = '%%%ds %%-%ds %%-%ds %%%ds %%%ds %%s' % tuple(maxlens)

        lines = []
        for fields in fieldlines:
            s = fmt % fields
            lines.append(s)
        return lines
    def open(self):
        self.lines = self._get_lines()
    def reload(self):
        lines = self._get_lines()
        self.set_lines(lines, force=True)
    def save(self, force=False):
        raise Exception, "can't save a directory buffer"
    def save_as(self, path):
        raise Exception, "can't save a directory buffer"

class ArchiveBuffer(DirBuffer):
    btype = 'archive'
    types = [
        ['.tar', 'tar xf %(archive)r -C %(dir)r'],
        ['.tgz', 'tar xfz %(archive)r -C %(dir)r'],
        ['.tar.gz', 'tar xfz %(archive)r -C %(dir)r'],
        ['.tar.bz2', 'tar xfj %(archive)r -C %(dir)r'],
        #['.gz', 'gunzip %(archive)r'],
        #['.bz2', 'bunzip2 %(archive)r'],
        ['.zip', 'unzip -qq %(archive)r -d %(dir)r'],
        ['.jar', 'unzip -qq %(archive)r -d %(dir)r'],
    ]
    def __init__(self, path, name=None):
        self.archive = os.path.realpath(path)
        for suffix, cmd in self.types:
            if self.archive.endswith(suffix):
                path = tempfile.mkdtemp()
                cwd = os.getcwd()
                os.chdir(path)
                s = cmd % {'archive': self.archive, 'dir': path}
                os.chdir(cwd)
                retval = os.system(s)
                if retval != 0: raise Exception("%r failed" % s)
        DirBuffer.__init__(self, path, name)

    def close(self):
        shutil.rmtree(self.path)

class PathListBuffer(DirBuffer):
    btype = 'pathlist'
    def __init__(self, name, paths):
        Buffer.__init__(self)
        self.paths = list(paths)
        self.path  = os.getcwd()
        self._name = name
        self.settings['hide-dot']  = False
        self.settings['type-sort'] = False
    def path_exists(self):
        raise Exception
    def get_names(self):
        cwd = os.getcwd()
        return [x.replace(cwd, '.', 1) for x in self.paths]
    def _make_path(self, name):
        if name.startswith('.'):
            return name.replace('.', os.getcwd(), 1)
        else:
            return name
    def name(self):
        return self._name