#
# Copyright (c) 2015-2023 Thierry Florac <tflorac AT ulthar.net>
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#

"""PyAMS_*** module

"""

from hypatia.catalog import CatalogQuery
from hypatia.interfaces import ICatalog
from hypatia.query import And, Eq, Or
from pyramid.events import subscriber
from pyramid.httpexceptions import HTTPForbidden
from zope.interface import Interface

from pyams_app_msc.feature.profile import IUserProfile
from pyams_app_msc.shared.theater import IMovieTheater
from pyams_catalog.query import CatalogResultSet
from pyams_form.interfaces.form import IAJAXFormRenderer
from pyams_i18n.interfaces import II18n
from pyams_layer.interfaces import IPyAMSLayer
from pyams_pagelet.pagelet import pagelet_config
from pyams_portal.skin.page import PortalContextIndexPage
from pyams_security.interfaces import LOGIN_REFERER_KEY
from pyams_security.interfaces.plugin import IAuthenticatedPrincipalEvent
from pyams_security.utility import get_principal
from pyams_security_views.interfaces.login import ILoginView
from pyams_site.interfaces import ISiteRoot
from pyams_template.template import template_config
from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
from pyams_utils.factory import get_interface_base_name
from pyams_utils.registry import get_utility
from pyams_utils.url import absolute_url

__docformat__ = 'restructuredtext'

from pyams_app_msc import _


@adapter_config(required=(Interface, IPyAMSLayer, ILoginView),
                provides=IAJAXFormRenderer)
class LoginFormAJAXRenderer(ContextRequestViewAdapter):
    """Login form renderer"""

    def render(self, changes):  # pylint: disable=unused-argument
        """AJAX form renderer"""
        status = {
            'status': 'redirect'
        }
        request = self.request
        session = request.session
        hash = request.params.get('login_form.widgets.hash', '')
        if hash:
            if LOGIN_REFERER_KEY in session:
                status['location'] = f"{session[LOGIN_REFERER_KEY] or '/'}{hash}"
                del session[LOGIN_REFERER_KEY]
            else:
                status['location'] = f'/{hash}'
        else:
            principal_id = self.view.finished_state.get('changes')
            if principal_id:
                catalog = get_utility(ICatalog)
                query = And(Eq(catalog['object_types'], get_interface_base_name(IMovieTheater)),
                            Or(Eq(catalog['role:msc:manager'], principal_id),
                               Eq(catalog['role:msc:operator'], principal_id),
                               Eq(catalog['role:msc:contributor'], principal_id),
                               Eq(catalog['role:msc:reader'], principal_id)))
                theaters = list(CatalogResultSet(CatalogQuery(catalog).query(query)))
                if len(theaters) == 1:
                    theater = theaters[0]
                    status['location'] = absolute_url(theater, request, 'admin')
                elif len(theaters) > 1:
                    status['location'] = absolute_url(request.root, request,
                                                      'select-admin-theater.html')
                else:
                    session = request.session
                    if LOGIN_REFERER_KEY in session:
                        status['location'] = session[LOGIN_REFERER_KEY]
                        del session[LOGIN_REFERER_KEY]
                    else:
                        status['location'] = absolute_url(request.context, request)
        return status


@subscriber(IAuthenticatedPrincipalEvent)
def handle_authenticated_principal(event):
    """Check for inactive profile when authenticated"""
    principal = get_principal(principal_id=event.principal_id)
    profile = IUserProfile(principal)
    if not profile.active:
        raise HTTPForbidden(_("User profile is disabled!"))


@pagelet_config(name='select-admin-theater.html',
                context=ISiteRoot, layer=IPyAMSLayer)
@template_config(template='templates/select-admin-theater.pt',
                 layer=IPyAMSLayer)
class TheaterSelectionView(PortalContextIndexPage):
    """Theater selection view"""

    def get_theaters(self):
        """Theaters list getter"""
        principal_id = self.request.principal.id
        catalog = get_utility(ICatalog)
        query = And(Eq(catalog['object_types'], get_interface_base_name(IMovieTheater)),
                    Or(Eq(catalog['role:msc:manager'], principal_id),
                       Eq(catalog['role:msc:operator'], principal_id),
                       Eq(catalog['role:msc:contributor'], principal_id),
                       Eq(catalog['role:msc:reader'], principal_id)))
        yield from sorted(CatalogResultSet(CatalogQuery(catalog).query(query)),
                          key=lambda x: II18n(x).query_attribute('title', request=self.request))
