# coding: utf-8
from __future__ import absolute_import
try:
    import cherrypy
    HAS_CHERRYPY = True
except ImportError:
    HAS_CHERRYPY = False

import os

from salttesting.runtests import RUNTIME_VARS

if HAS_CHERRYPY:
    from salttesting.cherrypytest.base import BaseCherryPyTestCase
else:
    from salttesting.unit import TestCase, skipIf

    @skipIf(HAS_CHERRYPY is False, 'The CherryPy python package needs to be installed')
    class BaseCherryPyTestCase(TestCase):
        pass

    class BaseToolsTest(BaseCherryPyTestCase):
        pass


class BaseRestCherryPyTest(BaseCherryPyTestCase):
    '''
    A base TestCase subclass for the rest_cherrypy module

    This mocks all interactions with Salt-core and sets up a dummy
    (unsubscribed) CherryPy web server.
    '''
    __opts__ = None

    def __init__(self, *args, **kwargs):
        super(BaseRestCherryPyTest, self).__init__(*args, **kwargs)

        # Late import
        import salt.config

        master_conf = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, 'master')
        self.config = salt.config.client_config(master_conf)

    def setUp(self, *args, **kwargs):
        # Late import
        from salt.netapi.rest_cherrypy import app

        # Make a local reference to the CherryPy app so we can mock attributes.
        self.app = app

        __opts__ = self.config.copy()
        __opts__.update(self.__opts__ or {
            'external_auth': {
                'auto': {
                    'saltdev': [
                        '@wheel',
                        '@runner',
                        '.*',
                    ],
                }
            },
            'rest_cherrypy': {
                'port': 8000,
                'debug': True,
            },
        })

        root, apiopts, conf = app.get_app(__opts__)

        cherrypy.tree.mount(root, '/', conf)
        cherrypy.server.unsubscribe()
        cherrypy.engine.start()

    def tearDown(self):
        cherrypy.engine.exit()


class Root(object):
    '''
    The simplest CherryPy app needed to test individual tools
    '''
    exposed = True

    _cp_config = {}

    def GET(self):
        return {'return': ['Hello world.']}

    def POST(self, *args, **kwargs):
        return {'return': [{'args': args}, {'kwargs': kwargs}]}


if HAS_CHERRYPY:
    class BaseToolsTest(BaseCherryPyTestCase):  # pylint: disable=E0102
        '''
        A base class so tests can selectively turn individual tools on for testing
        '''
        conf = {
            '/': {
                'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            },
        }

        def setUp(self):
            Root._cp_config = self._cp_config
            root = Root()

            cherrypy.tree.mount(root, '/', self.conf)
            cherrypy.server.unsubscribe()
            cherrypy.engine.start()

        def tearDown(self):
            cherrypy.engine.exit()
