#!/usr/bin/env python

#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import os
import json
import urllib
import urllib2
import sys
import pwd
import errno
import fcntl
import logging
import time

from threading import Lock
from collections import deque

import fuse

log = logging.getLogger(__name__)

logging.basicConfig()

fuse.fuse_python_api = (0, 2)
fuse.feature_assert('stateful_files', 'has_init')


class check_access(object):

    def __init__(self, *args, **kwargs):
        self._args = args
        self._kwargs = kwargs

    def __call__(self, func):
        def wrapper(inst, *args, **kwargs):
            new_args = list(args)
            new_kwargs = dict(kwargs)
            for i, (mode, path) in enumerate(zip(self._args, args)):
                new_args[i] = self.check(inst, path, mode)
            for name, mode in self._kwargs.iteritems():
                new_kwargs[name] = self.check(inst, kwargs.get(name), mode)
            return func(inst, *new_args, **new_kwargs)
        return wrapper

    def check(self, inst, path, mode):
        if mode is None:
            return
        rc = inst.access(path, mode)
        if rc:
            raise OSError(errno.EPERM, path, 'Permission denied')


class check_and_translate(check_access):

    def check(self, inst, path, mode):
        super(check_and_translate, self).check(inst, path, mode)
        return inst._to_global(path)


def flag2mode(flags):
    md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
    m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
    if flags | os.O_APPEND:
        m = m.replace('w', 'a', 1)
    return m


class AccessFS(fuse.Fuse):

    def __init__(self, *args, **kw):
        super(AccessFS, self).__init__(*args, **kw)
        self.root = '/'
        self.auth_method = 'unix'
        self.permission_host = 'http://localhost:8080'
        self.permission_cache_timeout = 30
        self.permission_cache_size = 1024
        self.file_class = self.make_file_class()
        self.perm_cache = None

    def getattr(self, path):
        return os.lstat("." + path)

    def readlink(self, path):
        self._assert_access(path, os.R_OK)
        return os.readlink("." + path)

    def readdir(self, path, offset):
        print 'Readdir!'
        for e in os.listdir("." + path):
            yield fuse.Direntry(e)

    def unlink(self, path):
        self._assert_access(path, os.W_OK)
        os.unlink("." + path)

    def rmdir(self, path):
        self._assert_access(path, os.W_OK)
        os.rmdir("." + path)

    def symlink(self, path, path1):
        self._assert_access(path, os.W_OK)
        os.symlink(path, "." + path1)

    def rename(self, path, path1):
        self._assert_access(path, os.R_OK | os.W_OK)
        self._assert_access(path1, os.R_OK | os.W_OK)
        os.rename("." + path, "." + path1)

    def link(self, path, path1):
        self._assert_access(path, os.R_OK)
        self._assert_access(path1, os.W_OK)
        os.link("." + path, "." + path1)

    def chmod(self, path, mode):
        self._assert_access(path, os.W_OK)
        os.chmod("." + path, mode)

    def chown(self, path, user, group):
        self._assert_access(path, os.W_OK)
        os.chown("." + path, user, group)

    def truncate(self, path, len):
        self._assert_access(path, os.W_OK)
        f = open("." + path, "a")
        f.truncate(len)
        f.close()

    def mknod(self, path, mode, dev):
        self._assert_access(path, os.W_OK)
        os.mknod("." + path, mode, dev)

    def mkdir(self, path, mode):
        self._assert_access(path, os.W_OK)
        os.mkdir("." + path, mode)

    def utime(self, path, times):
        os.utime("." + path, times)

    def access(self, path, mode):
        if mode & (os.R_OK | os.W_OK) == 0:
            return
        ctx = fuse.FuseGetContext()
        entry = self.perm_cache.get(ctx['uid'], path)
        if (mode & entry) != mode:
            return -errno.EACCES

    def _assert_access(self, path, mode):
        rc = self.access(path, mode)
        if rc:
            raise OSError(errno.EPERM, path, 'Permission denied')

    def statfs(self):
        """
        Should return an object with statvfs attributes (f_bsize, f_frsize...).
        Eg., the return value of os.statvfs() is such a thing (since py 2.2).
        If you are not reusing an existing statvfs object, start with
        fuse.StatVFS(), and define the attributes.

        To provide usable information (ie., you want sensible df(1)
        output, you are suggested to specify the following attributes:

            - f_bsize - preferred size of file blocks, in bytes
            - f_frsize - fundamental size of file blcoks, in bytes
                [if you have no idea, use the same as blocksize]
            - f_blocks - total number of blocks in the filesystem
            - f_bfree - number of free blocks
            - f_files - total number of file inodes
            - f_ffree - nunber of free file inodes
        """

        return os.statvfs(".")

    def fsinit(self):
        uid_cache = UnixUsernameCache()
        self.perm_cache = PermissionCache(
            uid_cache,
            self.permission_host,
            self.permission_cache_timeout,
            self.permission_cache_size)
        os.chdir(self.root)

    def make_file_class(self):
        class FSAccessFile(AccessFile):
            filesystem = self
        return FSAccessFile


class AccessFile(fuse.FuseFileInfo):
    direct_io = False
    keep_cache = False
    needs_write = (
        os.O_WRONLY
        | os.O_RDWR
        | os.O_APPEND
        | os.O_CREAT
        | os.O_TRUNC)

    def __init__(self, path, flags, *mode):
        access_mode = os.R_OK
        if flags & self.needs_write:
            access_mode |= os.W_OK
        self.filesystem._assert_access(path, access_mode)
        self.file = os.fdopen(os.open("." + path, flags, *mode),
                              flag2mode(flags))
        self.fd = self.file.fileno()

    def read(self, length, offset):
        self.file.seek(offset)
        return self.file.read(length)

    def write(self, buf, offset):
        self.file.seek(offset)
        self.file.write(buf)
        return len(buf)

    def release(self, flags):
        self.file.close()

    def _fflush(self):
        if 'w' in self.file.mode or 'a' in self.file.mode:
            self.file.flush()

    def fsync(self, isfsyncfile):
        self._fflush()
        if isfsyncfile and hasattr(os, 'fdatasync'):
            os.fdatasync(self.fd)
        else:
            os.fsync(self.fd)

    def flush(self):
        self._fflush()
        # cf. xmp_flush() in fusexmp_fh.c
        os.close(os.dup(self.fd))

    def fgetattr(self):
        return os.fstat(self.fd)

    def ftruncate(self, len):
        self.file.truncate(len)

    def lock(self, cmd, owner, **kw):
        # The code here is much rather just a demonstration of the locking
        # API than something which actually was seen to be useful.

        # Advisory file locking is pretty messy in Unix, and the Python
        # interface to this doesn't make it better.
        # We can't do fcntl(2)/F_GETLK from Python in a platfrom independent
        # way. The following implementation *might* work under Linux.
        #
        # if cmd == fcntl.F_GETLK:
        #     import struct
        #
        #     lockdata = struct.pack('hhQQi', kw['l_type'], os.SEEK_SET,
        #                            kw['l_start'], kw['l_len'], kw['l_pid'])
        #     ld2 = fcntl.fcntl(self.fd, fcntl.F_GETLK, lockdata)
        #     flockfields = ('l_type', 'l_whence', 'l_start', 'l_len', 'l_pid')
        #     uld2 = struct.unpack('hhQQi', ld2)
        #     res = {}
        #     for i in xrange(len(uld2)):
        #          res[flockfields[i]] = uld2[i]
        #
        #     return fuse.Flock(**res)

        # Convert fcntl-ish lock parameters to Python's weird
        # lockf(3)/flock(2) medley locking API...
        op = {fcntl.F_UNLCK: fcntl.LOCK_UN,
              fcntl.F_RDLCK: fcntl.LOCK_SH,
              fcntl.F_WRLCK: fcntl.LOCK_EX}[kw['l_type']]
        if cmd == fcntl.F_GETLK:
            return -errno.EOPNOTSUPP
        elif cmd == fcntl.F_SETLK:
            if op != fcntl.LOCK_UN:
                op |= fcntl.LOCK_NB
        elif cmd == fcntl.F_SETLKW:
            pass
        else:
            return -errno.EINVAL

        fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len'])


class PermissionCache(object):

    def __init__(self, uid_cache, host, timeout=30, size=1024):
        self._host = host
        self._timeout = timeout
        self._size = size
        self._data = {}
        self._entries = deque()
        self._lock = Lock()
        self._uid_cache = uid_cache

    def get(self, uid, path):
        try:
            entry, timestamp = self._data[uid, path]
            elapsed = time.time() - timestamp
            if elapsed > self._timeout:
                print 'Timeout!', elapsed
                uname = self._uid_cache.get(uid)
                entry = self._refresh_result(
                    uid, path, self._api_lookup(uname, path))
                return entry
            return entry
        except KeyError:
            pass
        uname = self._uid_cache.get(uid)
        try:
            entry = self._api_lookup(uname, path)
        except:
            entry = 0
            log.exception('Error checking access for %s', path)
        self._save_result(uid, path, entry)
        return entry

    def _api_lookup(self, uname, path):
        if path.count('/') < 3:
            return os.R_OK
        path = self._mangle(path)
        url = (
            self._host
            + '/auth/repo_permissions?'
            + urllib.urlencode(dict(
                repo_path=path,
                username=uname)))
        print 'Checking access for %s at %s (%s)' % (uname, url, path)
        fp = urllib2.urlopen(url)
        result = json.load(fp)
        print result
        entry = 0
        if result['allow_read']:
            entry |= os.R_OK
        if result['allow_write']:
            entry |= os.W_OK
        return entry

    def _refresh_result(self, uid, path, value):
        with self._lock:
            if (uid, path) in self._data:
                self._data[uid, path] = (value, time.time())
            else:
                if len(self._data) >= self._size:
                    k = self._entries.popleft()
                    del self._data[k]
                self._data[uid, path] = (value, time.time())
                self._entries.append((uid, path))
        return value

    def _save_result(self, uid, path, value):
        with self._lock:
            if len(self._data) >= self._size:
                k = self._entries.popleft()
                del self._data[k]
            self._data[uid, path] = (value, time.time())
            self._entries.append((uid, path))

    def _mangle(self, path):
        '''Convert paths from the form /SCM/neighborhood/project/a/b/c to
        /SCM/project.neighborhood/a/b/c
        '''
        parts = [p for p in path.split(os.path.sep) if p]
        scm, nbhd, proj, rest = parts[0], parts[1], parts[2], parts[3:]
        parts = ['/SCM/%s.%s' % (proj, nbhd)] + rest
        return '/'.join(parts)


class UnixUsernameCache(object):

    def __init__(self):
        self._cache = {}

    def get(self, uid):
        try:
            return self._cache[uid]
        except KeyError:
            pass
        uname = pwd.getpwuid(uid).pw_name
        self._cache[uid] = uname
        return uname


def main():

    usage = """
Userspace nullfs-alike: mirror the filesystem tree from some point on.

""" + fuse.Fuse.fusage

    server = AccessFS(version="%prog " + fuse.__version__,
                      usage=usage,
                      dash_s_do='setsingle')

    server.parser.add_option(mountopt="root", metavar="PATH", default='/',
                             help="mirror filesystem from under PATH [default: %default]")
    server.parse(values=server, errex=1)

    try:
        if server.fuse_args.mount_expected():
            os.chdir(server.root)
    except OSError:
        print >> sys.stderr, "can't enter root of underlying filesystem"
        sys.exit(1)

    server.main()


if __name__ == '__main__':
    main()
