# Copyright 2012 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 OpenStack Foundation
# Copyright 2012 Nebula, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from django.conf import settings
from django.contrib.auth.models import User  # noqa
from django.core.exceptions import ImproperlyConfigured  # noqa
from django.core import urlresolvers
from django.utils.importlib import import_module  # noqa
from six import moves

import horizon
from horizon import base
from horizon import conf
from horizon.test import helpers as test
from horizon.test.test_dashboards.cats.dashboard import Cats  # noqa
from horizon.test.test_dashboards.cats.kittens.panel import Kittens  # noqa
from horizon.test.test_dashboards.cats.tigers.panel import Tigers  # noqa
from horizon.test.test_dashboards.dogs.dashboard import Dogs  # noqa
from horizon.test.test_dashboards.dogs.puppies.panel import Puppies  # noqa


class MyDash(horizon.Dashboard):
    name = "My Dashboard"
    slug = "mydash"
    default_panel = "myslug"


class MyPanel(horizon.Panel):
    name = "My Panel"
    slug = "myslug"
    urls = 'horizon.test.test_dashboards.cats.kittens.urls'


class AdminPanel(horizon.Panel):
    name = "Admin Panel"
    slug = "admin_panel"
    permissions = ("horizon.test",)
    urls = 'horizon.test.test_dashboards.cats.kittens.urls'


class RbacNoAccessPanel(horizon.Panel):
    name = "RBAC Panel No"
    slug = "rbac_panel_no"

    def allowed(self, context):
        return False


class RbacYesAccessPanel(horizon.Panel):
    name = "RBAC Panel Yes"
    slug = "rbac_panel_yes"


class BaseHorizonTests(test.TestCase):

    def setUp(self):
        super(BaseHorizonTests, self).setUp()
        # Adjust our horizon config and register our custom dashboards/panels.
        self.old_default_dash = settings.HORIZON_CONFIG['default_dashboard']
        settings.HORIZON_CONFIG['default_dashboard'] = 'cats'
        self.old_dashboards = settings.HORIZON_CONFIG['dashboards']
        settings.HORIZON_CONFIG['dashboards'] = ('cats', 'dogs')
        base.Horizon.register(Cats)
        base.Horizon.register(Dogs)
        Cats.register(Kittens)
        Cats.register(Tigers)
        Dogs.register(Puppies)
        # Trigger discovery, registration, and URLconf generation if it
        # hasn't happened yet.
        base.Horizon._urls()
        # Store our original dashboards
        self._discovered_dashboards = base.Horizon._registry.keys()
        # Gather up and store our original panels for each dashboard
        self._discovered_panels = {}
        for dash in self._discovered_dashboards:
            panels = base.Horizon._registry[dash]._registry.keys()
            self._discovered_panels[dash] = panels

    def tearDown(self):
        super(BaseHorizonTests, self).tearDown()
        # Restore our settings
        settings.HORIZON_CONFIG['default_dashboard'] = self.old_default_dash
        settings.HORIZON_CONFIG['dashboards'] = self.old_dashboards
        # Destroy our singleton and re-create it.
        base.HorizonSite._instance = None
        del base.Horizon
        base.Horizon = base.HorizonSite()
        # Reload the convenience references to Horizon stored in __init__
        moves.reload_module(import_module("horizon"))
        # Re-register our original dashboards and panels.
        # This is necessary because autodiscovery only works on the first
        # import, and calling reload introduces innumerable additional
        # problems. Manual re-registration is the only good way for testing.
        self._discovered_dashboards.remove(Cats)
        self._discovered_dashboards.remove(Dogs)
        for dash in self._discovered_dashboards:
            base.Horizon.register(dash)
            for panel in self._discovered_panels[dash]:
                dash.register(panel)

    def _reload_urls(self):
        """Clears out the URL caches, reloads the root urls module, and
        re-triggers the autodiscovery mechanism for Horizon. Allows URLs
        to be re-calculated after registering new dashboards. Useful
        only for testing and should never be used on a live site.
        """
        urlresolvers.clear_url_caches()
        moves.reload_module(import_module(settings.ROOT_URLCONF))
        base.Horizon._urls()


class HorizonTests(BaseHorizonTests):

    def test_registry(self):
        """Verify registration and autodiscovery work correctly.

        Please note that this implicitly tests that autodiscovery works
        by virtue of the fact that the dashboards listed in
        ``settings.INSTALLED_APPS`` are loaded from the start.
        """
        # Registration
        self.assertEqual(2, len(base.Horizon._registry))
        horizon.register(MyDash)