# RiveScript-Python
#
# This code is released under the MIT License.
# See the "LICENSE" file for more information.
#
# https://www.rivescript.com/

from __future__ import unicode_literals
import copy

class SessionManager(object):
    """Base class for session management for RiveScript.

    The session manager keeps track of getting and setting user variables,
    for example when the ``<set>`` or ``<get>`` tags are used in RiveScript
    or when the API functions like ``set_uservar()`` are called.

    By default RiveScript stores user sessions in memory and provides methods
    to export and import them (e.g. to persist them when the bot shuts down
    so they can be reloaded). If you'd prefer a more 'active' session storage,
    for example one that puts user variables into a database or cache, you can
    create your own session manager that extends this class and implements its
    functions.

    See the ``eg/sessions`` example from the source of rivescript-python at
    https://github.com/aichaos/rivescript-python for an example.

    The constructor takes no required parameters. You can feel free to define
    ``__init__()`` however you need to.
    """

    def set(self, username, args):
        """Set variables for a user.

        Args:
            username (str): The username to set variables for.
            args (dict): Key/value pairs of variables to set for the user.
                The values are usually strings, but they can be other types
                as well (e.g. arrays or other dicts) for some internal data
                structures such as input/reply history. A value of ``NoneType``
                should indicate that the key should be deleted from the session
                store.
        """
        raise NotImplementedError

    def get(self, username, key):
        """Retrieve a stored variable for a user.

        If the user doesn't exist, this should return ``None``. If the user
        *does* exist, but the key does not, this should return the
        string value ``"undefined"``.

        Args:
            username (str): The username to retrieve variables for.
            key (str): The specific variable name to retrieve.

        Returns:
            str: The value of the requested key, "undefined", or ``NoneType``.
        """
        raise NotImplementedError

    def get_any(self, username):
        """Retrieve all stored variables for a user.

        If the user doesn't exist, this should return ``None``.

        Args:
            username (str): The username to retrieve variables for.

        Returns:
            dict: Key/value pairs of all stored data for the user, or ``NoneType``.
        """
        raise NotImplementedError

    def get_all(self):
        """Retrieve all variables about all users.

        This should return a dict of dicts, where the top level keys are the
        usernames of every user your bot has data for, and the values are dicts
        of key/value pairs of those users. For example::

            { "user1": {
                "topic": "random",
                "name": "Alice",
                },
              "user2": {
                "topic": "random",
                "name": "Bob",
                },
            }

        Returns:
            dict
        """
        raise NotImplementedError

    def reset(self, username):
        """Reset all variables stored about a particular user.

        Args:
            username (str): The username to flush all data for.
        """
        raise NotImplementedError

    def reset_all(self):
        """Reset all variables for all users."""
        raise NotImplementedError

    def freeze(self, username):
        """Make a snapshot of the user's variables.

        This should clone and store a snapshot of all stored variables for the
        user, so that they can later be restored with ``thaw()``. This
        implements the RiveScript ``freeze_uservars()`` method.

        Args:
            username (str): The username to freeze variables for.
        """
        raise NotImplementedError

    def thaw(self, username, action="thaw"):
        """Restore the frozen snapshot of variables for a user.

        This should replace *all* of a user's variables with the frozen copy
        that was snapshotted with ``freeze()``. If there are no frozen
        variables, this function should be a no-op (maybe issue a warning?)

        Args:
            username (str): The username to restore variables for.
            action (str):
                An action to perform on the variables. Valid options are:

                * ``thaw``: Restore the variables and delete the frozen copy (default).
                * ``discard``: Don't restore the variables, just delete the frozen copy.
                * ``keep``: Restore the variables and keep the copy still.
        """
        raise NotImplementedError

    def default_session(self):
        """The default session data for a new user.

        You do not need to override this function. This returns a ``dict`` with
        the default key/value pairs for new sessions. By default, the
        session variables are as follows::

            {
                "topic": "random"
            }

        Returns:
            dict: A dict of default key/value pairs for new user sessions.
        """
        return dict(