from pyramid.settings import (
    asbool,
    aslist,
    )

from .interfaces import (
    IAuthSourceService,
    )

from .policy import (
    AuthServicePolicy,
    )

from .sources import (
    SessionAuthSourceInitializer,
    CookieAuthSourceInitializer,
    )

from .util import (
    int_or_none,
    kw_from_settings,
    )

default_settings = (
    ('source', str, ''),
    ('cookie.cookie_name', str, 'auth'),
    ('cookie.max_age', int_or_none, None),
    ('cookie.httponly', asbool, True),
    ('cookie.path', str, '/'),
    ('cookie.domains', aslist, []),
    ('cookie.debug', asbool, False),
    ('session.value_key', str, 'sanity.'),
)

def init_cookie_source(config, settings):
    if 'authsanity.secret' not in settings:
        raise RuntimeError('authsanity.secret is required for cookie based storage')

    kw = kw_from_settings(settings, 'authsanity.cookie.')

    config.register_service_factory(CookieAuthSourceInitializer(settings['authsanity.secret'], **kw), iface=IAuthSourceService)

def init_session_source(config, settings):
    kw = kw_from_settings(settings, 'authsanity.session.')

    config.register_service_factory(SessionAuthSourceInitializer(**kw), iface=IAuthSourceService)


default_sources = {
    'cookie': init_cookie_source,
    'session': init_session_source,
}

# Stolen from pyramid_debugtoolbar
def parse_settings(settings):
    parsed = {}

    def populate(name, convert, default):
        name = '%s%s' % ('authsanity.', name)
        value = convert(settings.get(name, default))
        parsed[name] = value
    for name, convert, default in default_settings:
        populate(name, convert, default)
    return parsed


def includeme(config):
    # Go parse the settings
    settings = parse_settings(config.registry.settings)

    # Update the config
    config.registry.settings.update(settings)

    # include pyramid_services
    config.include('pyramid_services')

    if settings['authsanity.source'] in default_sources:
        default_sources[settings['authsanity.source']](config, config.registry.settings)

    config.set_authentication_policy(AuthServicePolicy())
