import commands, dirutil, grp, mailbox, method, mode, os.path, pwd, re, sys
import buffer, default, util, window
from mode.mutt import MuttGrammar
from lex import Grammar, PatternRule, RegionRule
from point import Point
from buffer import Buffer
from method import Method, Argument, arg
from method.shell import Interact

try:
    import eyeD3
    has_eyed3 = True
except ImportError:
    has_eyed3 = False

def _size_info(i):
    if i >= 1024 ** 2:
        return '%.2f MB' % (i * 1.0 / 1024 ** 2)
    elif i >= 1024:
        return '%.2f KB' % (i * 1.0 / 1024)
    else:
        return '%d B' % i

def _time_info(i):
    if i >= 60 ** 2:
        (j, k) = (i // 60 ** 2, i % 60 ** 2)
        return '%d:%02d:%02d secs' % (j, k // 60, k % 60)
    elif i >= 60:
        return '%d:%02d secs' % (i // 60, i % 60)
    else:
        return '%d secs' % i

def _str_info(s):
    if s:
        return str(s)
    else:
        return ''

def _num_pair_info(t):
    if t[0] and t[1]:
        return '%s/%s' % t
    elif t[0]:
        return str(t[0])
    elif t[1]:
        return '/%s' % t[1]
    else:
        return ''

class Mp3Buffer(Buffer):
    btype = 'mp3'
    def __init__(self, path):
        Buffer.__init__(self)
        self.path = util.expand_tilde(path)
        self.base = os.path.basename(self.path)
        self.af   = eyeD3.tag.Mp3AudioFile(self.path)
        self.tag  = self.af.getTag()
    def changed(self): return False
    def readonly(self): return True
    def path_exists(self): raise Exception
    def _make_path(self, name): raise Exception
    def save(self, force=False): raise Exception, "can't save an mbox"
    def save_as(self, path): raise Exception, "can't save an mbox"
    def name(self): return 'mp3:%s' % (self.base)
    def open(self): self.lines = self._get_lines()
    def reload(self): self.set_lines(self._get_lines(), force=True)
    def _get_lines(self):
        lines = [
            '# INFO',
            'Filename: ' + os.path.basename(self.af.fileName),
            'Filesize: ' + _size_info(self.af.fileSize),
            'Playtime: ' + _time_info(self.af.getPlayTime()),
            'Bitrate: ' + _str_info(self.af.getBitRate()),
            'Samplerate: ' + _str_info(self.af.getSampleFreq()) + ' kHz',
            '# ID3',
            'Artist: ' + _str_info(self.tag.getArtist()),
            'Album: ' + _str_info(self.tag.getAlbum()),
            'BPM: ' + _str_info(self.tag.getBPM()),
            #'CDID: ' + str(self.tag.getCDID()), #xyz
            'Comment: ' + _str_info(self.tag.getComment()),
            'DiscNum: ' + _num_pair_info(self.tag.getDiscNum()),
            'Genre: ' + _str_info(self.tag.getGenre()),
            'Publisher: ' + _str_info(self.tag.getPublisher()),
            'Title: ' + _str_info(self.tag.getTitle()),
            'TrackNum: ' + _num_pair_info(self.tag.getTrackNum()),
            #'Version: ' + _str_info(self.tag.getVersion()),
            'Year: ' + _str_info(self.tag.getYear()),
        ]
        return lines

class TagGrammar(Grammar):
    rules = [
        PatternRule(r'data', r'[^\\\n]+'),
        PatternRule(r'escaped', r'\\x[0-9a-fA-F]{2}'),
    ]
class Mp3Grammar(Grammar):
    rules = [
        PatternRule(r'comment', r'#.*\n$'),
        PatternRule(r'mp3_label', r'^[^:]+(?=: )'),
        RegionRule(r'mp3_tag', r': ', TagGrammar, r'\n$'),
    ]

class Mp3Refresh(Method):
    def _execute(self, w, **vargs):
        w.buffer.reload()
class Mp3Play(Method):
    def _execute(self, w, **vargs):
        pass
class Mpg123Play(Interact):
    args = []
    def _execute(self, w, **vargs):
        path = os.path.realpath(w.buffer.path)
        Interact._execute(self, w, bname='*Mpg123*', cmd='mpg123 %r' % path)

class Mp3OpenPath(Method):
    args = [arg('mp3', dt="path", p="Open MP3: ", dv=default.path_dirname,
                ld=True, h="mp3 to open")]
    def _execute(self, w, **vargs):
        b = Mp3Buffer(vargs['mp3'])
        b.open()
        window.Window(b, w.application, height=0, width=0, mode_name='mp3')
        w.application.add_buffer(b)
        w.application.switch_buffer(b)

class Mp3(mode.Fundamental):
    name    = 'Mp3'
    grammar = Mp3Grammar
    actions = [Mp3Refresh, Mp3OpenPath]
    colors  = {
        'mp3_label':       ('blue', 'default', 'bold'),
        'mp3_tag.start':   ('default', 'default', 'bold'),
        'mp3_tag.data':    ('green', 'default', 'bold'),
        'mp3_tag.escaped': ('magenta', 'default', 'bold'),
    }
    def __init__(self, w):
        mode.Fundamental.__init__(self, w)
        self.add_bindings('mp3-refresh', ('C-c r',))

if has_eyed3:
    install = Mp3.install
else:
    install = lambda *args: None