#
#  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>

import os
import signal
import time
import sys

from contextlib import contextmanager
from multiprocessing import Process
from .fuse import FUSE

from .._exceptions import ImplError
from .. import _signals, utils


# Just a custom exception to raise here, for identifying possible
# bugs with a fuse layer implementation
#
class FuseMountError(Exception):
    pass


# This is a convenience class which takes care of synchronizing the
# startup of FUSE and shutting it down.
#
# The implementations / subclasses should:
#
#   - Overload the instance initializer to add any parameters
#     needed for their fuse Operations implementation
#
#   - Implement create_operations() to create the Operations
#     instance on behalf of the superclass, using any additional
#     parameters collected in the initializer.
#
# Mount objects can be treated as contextmanagers, the volume
# will be mounted during the context.
#
# UGLY CODE NOTE:
#
#   This is a horrible little piece of code. The problem we face
#   here is that the highlevel libfuse API has fuse_main(), which
#   will either block in the foreground, or become a full daemon.
#
#   With the daemon approach, we know that the fuse is mounted right
#   away when fuse_main() returns, then the daemon will go and handle
#   requests on its own, but then we have no way to shut down the
#   daemon.
#
#   With the blocking approach, we still have it as a child process
#   so we can tell it to gracefully terminate; but it's impossible
#   to know when the mount is done, there is no callback for that
#
#   The solution we use here without digging too deep into the
#   low level fuse API, is to start a child process which will
#   run the fuse loop in foreground, and we block the parent
#   process until the volume is mounted with a busy loop with timeouts.
#
class Mount():

    # These are not really class data, they are
    # just here for the sake of having None setup instead
    # of missing attributes, since we do not provide any
    # initializer and leave the initializer to the subclass.
    #
    __mountpoint = None
    __operations = None
    __process = None
    __logfile = None

    ################################################
    #               User Facing API                #
    ################################################

    def __init__(self, fuse_mount_options=None):
        self._fuse_mount_options = {} if fuse_mount_options is None else fuse_mount_options

    # mount():
    #
    # User facing API for mounting a fuse subclass implementation
    #
    # Args:
    #    (str): Location to mount this fuse fs
    #
    def mount(self, mountpoint):

        assert self.__process is None

        self.__mountpoint = mountpoint
        self.__process = Process(target=self.__run_fuse, args=(self.__logfile.name,))

        # Ensure the child process does not inherit our signal handlers, if the
        # child wants to handle a signal then it will first set its own
        # handler, and then unblock it.
        with _signals.blocked([signal.SIGTERM, signal.SIGTSTP, signal.SIGINT], ignore=False):
            self.__process.start()

        while not os.path.ismount(mountpoint):
            if not self.__process.is_alive():
                self.__logfile.seek(0)
                stderr = self.__logfile.read()
                raise FuseMountError("Unable to mount {}: {}".format(mountpoint, stderr.decode().strip()))

            time.sleep(1 / 100)

    # unmount():
    #
    # User facing API for unmounting a fuse subclass implementation
    #
    def unmount(self):

        # Terminate child process and join
        if self.__process is not None:
            self.__process.terminate()
            self.__process.join()

            # Report an error if ever the underlying operations crashed for some reason.
            if self.__process.exitcode != 0:
                self.__logfile.seek(0)
                stderr = self.__logfile.read()

                raise FuseMountError("{} reported exit code {} when unmounting: {}"
                                     .format(type(self).__name__, self.__process.exitcode, stderr))

        self.__mountpoint = None
        self.__process = None

    # mounted():
    #
    # A context manager to run a code block with this fuse Mount
    # mounted, this will take care of automatically unmounting
    # in the case that the calling process is terminated.
    #
    # Args:
    #    (str): Location to mount this fuse fs
    #
    @contextmanager
    def mounted(self, mountpoint):

        with utils._tempnamedfile() as logfile:
            self.__logfile = logfile

            self.mount(mountpoint)
            try:
                with _signals.terminator(self.unmount):
                    yield
            finally:
                self.unmount()

        self.__logfile = None

    ################################################
    #               Abstract Methods               #
    ################################################

    # create_operations():
    #
    # Create an Operations class (from fusepy) and return it
    #
    # Returns:
    #    (Operations): A FUSE Operations implementation
    def create_operations(self):
        raise ImplError("Mount subclass '{}' did not implement create_operations()"
                        .format(type(self).__name__))

    ################################################
    #                Child Process                 #
    ################################################
    def __run_fuse(self, filename):
        # Override stdout/stderr to the file given as a pointer, that way our parent process can get our output
        out = open(filename, "w")
        os.dup2(out.fileno(), sys.stdout.fileno())
        os.dup2(out.fileno(), sys.stderr.fileno())

        # First become session leader while signals are still blocked
        #
        # Then reset the SIGTERM handler to the default and finally
        # unblock SIGTERM.
        #
        os.setsid()
        signal.signal(signal.SIGTERM, signal.SIG_DFL)
        signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGTERM])

        # Ask the subclass to give us an Operations object
        #
        self.__operations = self.create_operations()  # pylint: disable=assignment-from-no-return

        # Run fuse in foreground in this child process, internally libfuse
        # will handle SIGTERM and gracefully exit its own little main loop.
        #
        try:
            FUSE(self.__operations, self.__mountpoint, nothreads=True, foreground=True, nonempty=True,
                 **self._fuse_mount_options)
        except RuntimeError as exc:
            # FUSE will throw a RuntimeError with the exit code of libfuse as args[0]
            sys.exit(exc.args[0])

        # Explicit 0 exit code, if the operations crashed for some reason, the exit
        # code will not be 0, and we want to know about it.
        #
        sys.exit(0)
