#
#  Copyright (C) 2016 Stavros Korokithakis
#  Copyright (C) 2017 Codethink Limited
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
#
#  The filesystem operations implementation here is based
#  on some example code written by Stavros Korokithakis.

import errno
import os
import shutil
import stat
import tempfile

from .fuse import FuseOSError, Operations

from .mount import Mount


# SafeHardlinks()
#
# A FUSE mount which implements a copy on write hardlink experience.
#
# Args:
#     root (str): The underlying filesystem path to mirror
#     tmp (str): A directory on the same filesystem for creating temp files
#
class SafeHardlinks(Mount):

    def __init__(self, directory, tempdir, fuse_mount_options=None):
        self.directory = directory
        self.tempdir = tempdir
        if fuse_mount_options is None:
            fuse_mount_options = {}
        super().__init__(fuse_mount_options=fuse_mount_options)

    def create_operations(self):
        return SafeHardlinkOps(self.directory, self.tempdir)


# SafeHardlinkOps()
#
# The actual FUSE Operations implementation below.
#
class SafeHardlinkOps(Operations):

    def __init__(self, root, tmp):
        self.root = root
        self.tmp = tmp

    def _full_path(self, partial):
        if partial.startswith("/"):
            partial = partial[1:]
        path = os.path.join(self.root, partial)
        return path

    def _ensure_copy(self, full_path):
        try:
            # Follow symbolic links manually here
            real_path = os.path.realpath(full_path)
            file_stat = os.stat(real_path)

            # Dont bother with files that cannot be hardlinked, oddly it
            # directories actually usually have st_nlink > 1 so just avoid
            # that.
            #
            # We already wont get symlinks here, and stat will throw
            # the FileNotFoundError below if a followed symlink did not exist.
            #
            if not stat.S_ISDIR(file_stat.st_mode) and file_stat.st_nlink > 1:
                with tempfile.TemporaryDirectory(dir=self.tmp) as tempdir:
                    basename = os.path.basename(real_path)
                    temp_path = os.path.join(tempdir, basename)

                    # First copy, then unlink origin and rename
                    shutil.copy2(real_path, temp_path)
                    os.unlink(real_path)
                    os.rename(temp_path, real_path)

        except FileNotFoundError:
            # This doesnt exist yet, assume we're about to create it
            # so it's not a problem.
            pass

    ###########################################################
    #                     Fuse Methods                        #
    ###########################################################
    def access(self, path, mode):
        full_path = self._full_path(path)
        if not os.access(full_path, mode):
            raise FuseOSError(errno.EACCES)

    def chmod(self, path, mode):
        full_path = self._full_path(path)

        # Ensure copies on chmod
        self._ensure_copy(full_path)
        return os.chmod(full_path, mode)

    def chown(self, path, uid, gid):
        full_path = self._full_path(path)

        # Ensure copies on chown
        self._ensure_copy(full_path)
        return os.chown(full_path, uid, gid)

    def getattr(self, path, fh=None):
        full_path = self._full_path(path)
        st = os.lstat(full_path)
        return dict((key, getattr(st, key)) for key in (
            'st_atime', 'st_ctime', 'st_gid', 'st_mode',
            'st_mtime', 'st_nlink', 'st_size', 'st_uid', 'st_rdev'))

    def readdir(self, path, fh):
        full_path = self._full_path(path)

        dirents = ['.', '..']
        if os.path.isdir(full_path):
            dirents.extend(os.listdir(full_path))
        for r in dirents:
            yield r

    def readlink(self, path):
        pathname = os.readlink(self._full_path(path))
        if pathname.startswith("/"):
            # Path name is absolute, sanitize it.
            return os.path.relpath(pathname, self.root)
        else:
            return pathname

    def mknod(self, path, mode, dev):
        return os.mknod(self._full_path(path), mode, dev)

    def rmdir(self, path):
        full_path = self._full_path(path)
        return os.rmdir(full_path)

    def mkdir(self, path, mode):
        return os.mkdir(self._full_path(path), mode)

    def statfs(self, path):
        full_path = self._full_path(path)
        stv = os.statvfs(full_path)
        return dict((key, getattr(stv, key)) for key in (
            'f_bavail', 'f_bfree', 'f_blocks', 'f_bsize', 'f_favail',
            'f_ffree', 'f_files', 'f_flag', 'f_frsize', 'f_namemax'))

    def unlink(self, path):
        return os.unlink(self._full_path(path))

    def symlink(self, name, target):
        return os.symlink(target, self._full_path(name))

    def rename(self, old, new):
        return os.rename(self._full_path(old), self._full_path(new))

    def link(self, target, name):

        # When creating a hard link here, should we ensure the original
        # file is not a hardlink itself first ?
        #
        return os.link(self._full_path(name), self._full_path(target))

    def utimens(self, path, times=None):
        return os.utime(self._full_path(path), times)

    def open(self, path, flags):
        full_path = self._full_path(path)

        # If we're opening for writing, ensure it's a copy first
        if flags & os.O_WRONLY or flags & os.O_RDWR:
            self._ensure_copy(full_path)

        return os.open(full_path, flags)

    def create(self, path, mode, flags):
        full_path = self._full_path(path)

        # If it already exists, ensure it's a copy first
        self._ensure_copy(full_path)
        return os.open(full_path, flags, mode)

    def read(self, path, length, offset, fh):
        os.lseek(fh, offset, os.SEEK_SET)
        return os.read(fh, length)

    def write(self, path, buf, offset, fh):
        os.lseek(fh, offset, os.SEEK_SET)
        return os.write(fh, buf)

    def truncate(self, path, length, fh=None):
        full_path = self._full_path(path)
        with open(full_path, 'r+') as f:
            f.truncate(length)

    def flush(self, path, fh):
        return os.fsync(fh)

    def release(self, path, fh):
        return os.close(fh)

    def fsync(self, path, fdatasync, fh):
        return self.flush(path, fh)
