from cuchulu.modules.admin2.models.admin import UserAdmin2
from bottle import request
from cuchulu.libraries.sessions import get_session
from cuchulu.libraries.urls import redirect, make_url
from cuchulu.libraries.db.webmodel import WebModel
import inspect

class LoginPlugin(object):
    """Plugin for simple login"""

    name = 'login'
    api = 2
    
    def __init__(self, keyword='login', login_var='login', login_url='login'):
        """Simple bottle plugin for standard login
        
        Args:
            keyword (str): The variable name for activate the plugin
            login_var (str): The name used for define the login variable
            login_url (str): The url of the login page
        
        """
        
        self.keyword=keyword
        self.login_var=login_var
        self.login_url=login_url
        
        
    def setup(self, app):
        """Make sure that other installed plugins don't affect the same keyword argument.
        Args:
            app (Bottle): The app object used in the request. 
        
        """
        for other in app.plugins:
            if not isinstance(other, LoginPlugin): continue
            if other.keyword == self.keyword:
                raise PluginError("Found another login plugin with "\
                "conflicting settings (non-unique keyword).")

    def apply(self, callback, context):

        """Test if the original callback accepts a 'login' keyword.
        
        Ignore it if it does not need a login handle.
        
        Args:
            callback (function): The callback used in the plugin
            context (object): An object with the context of function
        
        Returns:
        
            function: return the result of the route
        
        """
        
        conf = context.config.get(self.keyword) or {}
        
        keyword = conf.get('keyword', self.keyword)
        
        args = inspect.getfullargspec(context.callback)[0]
        
        if keyword not in args:
            return callback
        
        def wrapper(*args, **kwargs):
            
            s=get_session()
            
            if self.login_var in s:

                rv = callback(*args, **kwargs)
                
                return rv
            
            else:
                #Check if remember_login cookie
                #, secret=config.key_encrypt

                redirect(make_url(self.login_url))
            
        # Replace the route callback with the wrapped one.
        return wrapper

class AdminLoginPlugin(LoginPlugin):
    """A plugin for admin things. DEPRECATED"""
    
    name = 'adminlogin'
    api = 2
    
    def __init__(self, keyword='login_admin'):
        
        self.keyword=keyword
            
        
class DbPlugin(object):
    """A Bottle plugin for create a connection to database"""

    name = 'db'
    api = 2
    
    def __init__(self, keyword='db'):
        """A Bottle plugin for create a connection to database"""
        
        
        self.keyword=keyword

        
    def setup(self, app):
        ''' Make sure that other installed plugins don't affect the same keyword argument.'''
        for other in app.plugins:
            if not isinstance(other, DbPlugin): continue
            if other.keyword == self.keyword:
                raise PluginError("Found another login plugin with "\
                "conflicting settings (non-unique keyword).")

    def apply(self, callback, context):

        """Test if the original callback accepts a 'db' keyword.
        
        Ignore it if it does not need a login handle.
        
        Args:
            callback (function): The callback used in the plugin
            context (object): An object with the context of function
            
        Returns:
        
            function: return the result of the route
        """
        
        conf = context.config.get('db') or {}
        
        keyword = conf.get('keyword', self.keyword)
        
        args = inspect.getfullargspec(context.callback)[0]
    
        if keyword not in args:
            return callback
        
        def wrapper(*args, **kwargs):
        
            kwargs['db']=WebModel.connection()

            try:

                rv = callback(*args, **kwargs)
                
            except:
                kwargs['db'].close()                
                raise
            
            kwargs['db'].close()
                
            return rv

        return wrapper
            
                    
        



