#-----------------------------------------------------------------------------
# Copyright (c) 2012 - 2022, Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
from __future__ import annotations # isort:skip

import pytest ; pytest

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

# Standard library imports
from types import ModuleType

# External imports
from tornado.web import RequestHandler

# Bokeh imports
from bokeh._testing.util.api import verify_all
from bokeh._testing.util.filesystem import with_file_contents, with_file_contents_async

# Module under test
import bokeh.server.auth_provider as bsa # isort:skip

#-----------------------------------------------------------------------------
# Setup
#-----------------------------------------------------------------------------

ALL = (
    'AuthModule',
    'AuthProvider',
    'NullAuth'
)

@pytest.fixture
def null_auth() -> bsa.NullAuth:
    return bsa.NullAuth()

#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------

Test___all__ = verify_all(bsa, ALL)

class TestNullAuth:
    def test_endpoints(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.endpoints == []

    def test_get_user(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.get_user == None

    async def test_get_user_async(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.get_user_async == None

    def test_login_url(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.login_url == None

    def test_get_login_url(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.get_login_url == None

    def test_login_handler(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.login_handler == None

    def test_logout_url(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.logout_url == None

    def test_logout_handler(self, null_auth: bsa.NullAuth) -> None:
        assert null_auth.logout_handler == None

class TestAuthModule_properties:
    def test_no_endpoints(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.endpoints == []

        with_file_contents("""
def get_user(): pass
def get_login_url(): pass
        """, func, suffix='.py')

        with_file_contents("""
def get_user(): pass
login_url = "/foo"
        """, func, suffix='.py')

    def test_login_url_endpoint(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.endpoints[0][0] == '/foo'
            assert issubclass(am.endpoints[0][1], RequestHandler)
        with_file_contents("""
from tornado.web import RequestHandler
def get_user(): pass
login_url = "/foo"
class LoginHandler(RequestHandler): pass
        """, func, suffix='.py')

    def test_logout_url_endpoint(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.endpoints[0][0] == '/bar'
            assert issubclass(am.endpoints[0][1], RequestHandler)
        with_file_contents("""
from tornado.web import RequestHandler
def get_user(): pass
login_url = "/foo"
logout_url = "/bar"
class LogoutHandler(RequestHandler): pass
        """, func, suffix='.py')

    def test_login_logout_url_endpoint(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            endpoints = sorted(am.endpoints)
            assert endpoints[0][0] == '/bar'
            assert issubclass(endpoints[0][1], RequestHandler)
            assert endpoints[1][0] == '/foo'
            assert issubclass(endpoints[1][1], RequestHandler)
        with_file_contents("""
def get_user(): pass
login_url = "/foo"
from tornado.web import RequestHandler
class LoginHandler(RequestHandler): pass
logout_url = "/bar"
from tornado.web import RequestHandler
class LogoutHandler(RequestHandler): pass
        """, func, suffix='.py')

    def test_get_user(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.get_user is not None
            assert am.get_user('handler') == 10

        with_file_contents("""
def get_user(handler): return 10
login_url = "/foo"
        """, func, suffix='.py')

    async def test_get_user_async(self) -> None:
        async def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.get_user_async is not None
            assert await am.get_user_async('handler') == 10

        await with_file_contents_async("""
async def get_user_async(handler): return 10
login_url = "/foo"
        """, func, suffix='.py')


    def test_login_url(self) -> None:
        def func(filename: str):
            am = bsa.AuthModule(filename)
            assert am.login_url == "/foo"
            assert am.get_login_url is None
            assert am.login_handler is None
            assert am.logout_url is None
            assert am.logout_handler is None

        with_file_contents("""
def get_user(handler): return 10
login_url = "/foo"
        """, func, suffix='.py')

    def test_get_login_url(self) -> None: