import os, commands, re, sets, tempfile
from subprocess import Popen, PIPE, STDOUT

import buffer, default, dirutil, regex, util, window
from point import Point
from method import DATATYPES, Method, Argument, arg

class OpenFile(Method):
    '''Open file in a new buffer, or go to file's open buffer'''
    args = [arg('filename', dt="path", p="Open File: ", dv=default.path_dirname,
                ld=True, h="file to open")]
    def _execute(self, w, **vargs):
        b = w.application.open_path(vargs['filename'])
        SwitchBuffer().execute(w, buffername=b.name())
class OpenAesFile(Method):
    '''Open AES encrypted file in a new buffer, or go to file's open buffer'''
    args = [arg('filename', dt="path", p="Open AES File: ",
                dv=default.path_dirname, h="file to open"),
            arg('password', p="Use AES Password: ",
                h="the AES password the file was encrypted with")]
    def _execute(self, w, **vargs):
        b = w.application.open_path(vargs['filename'], 'aes', vargs['password'])
        SwitchBuffer().execute(w, buffername=b.name())
        return

class ViewBufferParent(Method):
    def _execute(self, w, **vargs):
        b = w.buffer
        if not hasattr(b, 'path'):
            w.set_error('Buffer has no path')
        elif b.path == '/':
            w.set_error("Root directory has no parent")
        else:
            path = os.path.dirname(b.path)
            w.application.methods['open-file'].execute(w, filename=path)

class SwitchBuffer(Method):
    '''Switch to a different'''
    args = [arg('buffername', dt="buffer", p="Switch To Buffer: ",
                dv=default.last_buffer, h="name of the buffer to switch to")]
    def _pre_execute(self, w, **vargs):
        a = w.application
        if len(a.bufferlist.buffers) < 1:
            raise Exception, "No other buffers"
    def _execute(self, w, **vargs):
        name = vargs['buffername']
        buf = None
        if w.application.has_buffer_name(name):
            b = w.application.bufferlist.get_buffer_by_name(name)
            w.application.switch_buffer(b)
        else:
            w.set_error("buffer %r was not found" % name)
class KillBuffer(Method):
    '''Close the current buffer'''
    force = False
    args  = [arg('buffername', dt="buffer", p="Kill Buffer: ",
                 dv=default.current_buffer, h="name of the buffer to kill")]
    def _execute(self, w, **vargs):
        name = vargs['buffername']
        a  = w.application
        assert name in a.bufferlist.buffer_names, "Buffer %r does not exist" % name
        assert name != '*Scratch*', "Can't kill scratch buffer"
        self._to_kill    = a.bufferlist.buffer_names[name]
        self._old_window = w
        if self.force or not self._to_kill.changed():
            self._doit()
        else:
            self._prompt = "Buffer has unsaved changes; kill anyway? "
            a.open_mini_buffer(self._prompt, self._callback)
    def _doit(self):
        a = self._old_window.application
        b = self._to_kill
        a.close_buffer(b)
    def _callback(self, v):
        a = self._old_window.application
        if v == 'yes':
            self._doit()
            a.close_mini_buffer()
        elif v == 'no':
            a.close_mini_buffer()
        else:
            a.close_mini_buffer()
            a.set_error('Please type "yes" or "no"')

class ForceKillBuffer(KillBuffer):
    '''Close the current buffer, automatically discarding any changes'''
    force=True

class ListBuffers(Method):
    '''List all open buffers in a new buffer'''
    def _execute(self, w, **vargs):
        bl = w.application.bufferlist
        bnames = [b.name() for b in bl.buffers]
        bnames.sort()
        data = '\n'.join(bnames)
        w.application.data_buffer("*Buffers*", data, switch_to=True)
class SaveBufferAs(Method):
    '''Save the contents of a buffer to the specified path'''
    args = [arg('path', dt="path", p="Write file: ", ld=True,
                dv=default.current_working_dir, h="new path to use")]
    def _execute(self, w, **vargs):
        curr_buffer = w.buffer
        curr_buffer_name = curr_buffer.name()
        data = curr_buffer.make_string()
        path = os.path.realpath(os.path.expanduser(vargs['path']))
        w.set_error("got %r (%d)" % (path, len(data)))
        if w.application.has_buffer_name(path):
            w.set_error("buffer for %r is already open" % path)
            return
        w.application.file_buffer(path, data, switch_to=True)
        if curr_buffer_name != '*Scratch*':
            w.application.methods['kill-buffer'].execute(w, buffername=curr_buffer_name)
        else:
            curr_buffer.set_data('')
        w.set_error('Wrote %r' % path)
class SaveBuffer(Method):
    '''Save the contents of a buffer'''    
    def _execute(self, w, **vargs):
        if w.buffer.changed():
            w.buffer.save()
            w.set_error("Wrote %s" % (w.buffer.path))
        else:
            w.set_error("(No changes need to be saved)")