import datetime, grp, os, pwd, re, stat
from point import Point

def resolve_token(w, y=None):
    if y is None:
        p = Point(0, w.logical_cursor().y)
    else:
        p = Point(0, y)
    return w.get_next_token_by_type(p, 'dir_name')
def resolve_name(w, y=None):
    t = resolve_token(w, y)
    assert t is not None
    return t.string
def resolve_path(w, y=None):
    name = resolve_name(w)
    path = os.path.join(w.buffer.path, name)
    return path

def find_name(w, s):
    found = False
    y = 0
    c = w.logical_cursor()
    while not found and y < len(w.buffer.lines):
        t = resolve_token(w, y)
        if t.string == s:
            found = True
            break
        y += 1
    if found:
        w.application.methods['goto-line'].execute(w, lineno=y+1)
        p = Point(c.x, y)
        if not w.point_is_visible(p):
            w.goto(p)

def valid_owner(owner):
    if not owner:
        return False
    elif owner.isdigit():
        return True
    try:
        pwd.getpwnam(owner)
        return True
    except:
        return False
def valid_group(group):
    if not group:
        return False
    elif group.isdigit():
        return True
    try:
        grp.getgrnam(group)
        return True
    except:
        return False

def path_sort(a, b):
    try:
        x = cmp(a[0][0], b[0][0])
        if x != 0:
            return -x
        return cmp(a[5], b[5])
    except:
        raise Exception, repr(a) + ' ' + repr(b)

def path_fields(path, name):
    # let's escape some troublesome characters
    name = re.sub(r'([\a\b\n\r\t\v])', r'\\\1', name)
    # don't follow links
    info = os.lstat(path)

    # - regular, b block, c character, d directory, l symlink, p fifo
    # s socket, ? unknown
    perm = [' '] * 10
    if stat.S_ISREG(info.st_mode):
        perm[0] = '-'
    elif stat.S_ISBLK(info.st_mode):
        perm[0] = 'b'
    elif stat.S_ISCHR(info.st_mode):
        perm[0] = 'c'
    elif stat.S_ISDIR(info.st_mode):
        perm[0] = 'd'
    elif stat.S_ISLNK(info.st_mode):
        perm[0] = 'l'
    elif stat.S_ISFIFO(info.st_mode):
        perm[0] = 'p'
    elif stat.S_ISSOCK(info.st_mode):
        perm[0] = 's'
    else:
        perm[0] = '?'

    i = 1
    symbols = ('r', 'w', 'x')
    for bundle in ((stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR),
                   (stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP),
                   (stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH)):
        for j in range(0, 3):
            if info.st_mode & bundle[j]:
                perm[i] = symbols[j]
            else:
                perm[i] = '-'
            i += 1

    if info.st_mode & stat.S_ISUID:
        if perm[3] == 'x':
            perm[3] = 's'
        else:
            perm[3] = 'S'
    if info.st_mode & stat.S_ISGID:
        if perm[6] == 'x':
            perm[6] = 's'
        else:
            perm[6] = 'S'
    if info.st_mode & stat.S_ISVTX:
        if perm[9] == 'x':
            perm[9] = 't'
        else:
            perm[9] = 'T'

    perms = ''.join(perm)
    
    try:
        user  = pwd.getpwuid(info.st_uid)[0]
    except:
        user = str(info.st_uid)
    try:
        group  = grp.getgrgid(info.st_gid)[0]
    except:
        group = str(info.st_gid)

    size = info.st_size
    unit = 0
    units = ('B', 'K', 'M', 'G',)
    while unit < 3 and size > 1024:
        size = size / 1024
        unit += 1
    size = '%d%s' % (size, units[unit])

    mtime = datetime.datetime.fromtimestamp(info.st_mtime).strftime('%b %d %H:%M')

    fields = (perms, user, group, size, mtime, name)
    return fields