# Copyright (C) 2018, 2020 The Meme Factory, Inc.  http://www.karlpinc.com/

# This file is part of PGWUI_Common.
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see
# <http://www.gnu.org/licenses/>.
#

# Karl O. Pinc <kop@karlpinc.com>

'''Expose useful response "variables" to templates
'''

import logging
import pyramid.request

from .plugin import find_pgwui_components
from . import exceptions as ex

# Logging
log = logging.getLogger(__name__)


def route_path(request, page_name, source):
    '''Return the route path of the page's "source"
    '''
    try:
        return request.route_path(source)
    except KeyError as old_ex:
        raise ex.BadRouteError(page_name, old_ex)


def asset_path(request, page_name, source):
    '''Return the static path to the asset's "source"
    '''
    try:
        return request.static_path(source)
    except ValueError as old_ex:
        raise ex.BadAssetError(page_name, old_ex)


def url_of_page(request, page_name):
    '''Return a url to the page.  This may or may not be fully
    qualified, depending on what the user specifies in the settings.
    '''
    page_conf = request.registry.settings['pgwui'][page_name]
    type = page_conf['type']
    source = page_conf['source']
    if type == 'URL':
        return source
    if type == 'file':
        return request.route_path(f'pgwui_common.{page_name}')
    if type == 'route':
        return route_path(request, page_name, source)
    if type == 'asset':
        return asset_path(request, page_name, source)


def set_menu_url(request, urls):
    '''Add urls for pgwui_menu, return non-menu components
    '''
    try:
        menu_url = url_of_page(request, 'menu_page')
    except KeyError:
        try:
            menu_url = request.route_path('pgwui_menu')
        except KeyError:
            return []    # the pgwui_menu component is optional
    except ex.BadPathError as exp:
        return [exp]
    if menu_url != urls['pgwui_home']:
        urls['pgwui_menu'] = menu_url
    return []


def set_component_urls(request, urls):
    '''Add urls for each pgwui component to the 'urls' dict
    '''
    errors = set_menu_url(request, urls)
    components = find_pgwui_components()
    if 'pgwui_menu' in components:
        components.remove('pgwui_menu')

    for component in components:
        try:
            url = request.route_path(component)
        except KeyError:
            pass         # In case a component has no route
        else:
            urls.setdefault(component, url)

    return errors


def set_urls(request, urls):
    '''Build 'urls' dict with all the urls
    '''
    errors = []
    try:
        home_url = url_of_page(request, 'home_page')
    except ex.BadPathError as exp:
        errors.append(exp)
        # set_component_urls() requires a 'pgwui_home' key, and the error
        # means the program will exit and the value never be used.
        urls.setdefault('pgwui_home', None)
    else:
        urls.setdefault('pgwui_home', home_url)
    errors.extend(set_component_urls(request, urls))
    return errors


def add_urls_setting(config, settings):
    '''Add the 'urls' dict to settings, from the existing settings and
    route configuration
    '''
    urls = dict()
    # We could use introspection, but that would require pyramid_testing
    # be installed in a production enviornment.  And some RAM.
    request = pyramid.request.Request.blank('/')
    request.registry = config.registry
    errors = set_urls(request, urls)
    settings['pgwui']['urls'] = urls
    log.debug('Routing map of route names to url paths which is given'
              f' to the templates: {urls}')
    return errors
