"""
The HEA Server Activity Microservice manages activity events generated by other microservices. It uses the HEA
message broker and subscribes to all Activity types found in the heaobject.activity module.
"""

from heaserver.service import appproperty
from heaserver.service.runner import init_cmd_line, routes, start, web
from heaserver.service.db import mongo, mongoservicelib
from heaserver.service.wstl import builder_factory, action
from heaserver.service.messagebroker import subscriber_cleanup_context_factory
from heaobject.activity import DesktopObjectAction
from heaobject.root import DesktopObject

MONGODB_DESKTOP_OBJECT_ACTION_COLLECTION = 'desktopobjectactions'


@routes.get('/desktopobjectactions/{id}')
@action('heaserver-activity-desktopobjectaction-get-properties', rel='hea-properties')
@action('heaserver-activity-desktopobjectaction-get-old-object-uri', rel='hea-desktop-object', itemif='old_object_uri is not None and new_object_uri is None', path='{+old_object_uri}')
@action('heaserver-activity-desktopobjectaction-get-new-object-uri', rel='hea-desktop-object', itemif='new_object_uri is not None', path='{+new_object_uri}')
@action('heaserver-activity-desktopobjectaction-get-self', rel='self', path='/desktopobjectactions/{id}')
async def get_desktop_object_action(request: web.Request) -> web.Response:
    """
    Gets the desktop object action with the specified id.
    :param request: the HTTP request.
    :return: the requested desktop object action or Not Found.
    ---
    summary: A specific desktop object action.
    tags:
        - heaserver-activity
    parameters:
        - $ref: '#/components/parameters/id'
    responses:
      '200':
        $ref: '#/components/responses/200'
      '404':
        $ref: '#/components/responses/404'
    """
    return await mongoservicelib.get(request, MONGODB_DESKTOP_OBJECT_ACTION_COLLECTION)


@routes.get('/desktopobjectactions/byname/{name}')
@action('heaserver-activity-desktopobjectaction-get-self', rel='self', path='/desktopobjectactions/{id}')
async def get_desktop_object_action_by_name(request: web.Request) -> web.Response:
    """
    Gets the desktop object action with the specified name.
    :param request: the HTTP request.
    :return: the requested desktop object action or Not Found.
    ---
    summary: A specific desktop object action, by name.
    tags:
        - heaserver-activity
    parameters:
        - $ref: '#/components/parameters/name'
    responses:
      '200':
        $ref: '#/components/responses/200'
      '404':
        $ref: '#/components/responses/404'
    """
    return await mongoservicelib.get_by_name(request, MONGODB_DESKTOP_OBJECT_ACTION_COLLECTION)


@routes.get('/desktopobjectactions')
@routes.get('/desktopobjectactions/')
@action('heaserver-activity-desktopobjectaction-get-properties', rel='hea-properties')
@action('heaserver-activity-desktopobjectaction-get-old-object-uri', rel='hea-desktop-object', itemif='old_object_uri is not None and new_object_uri is None', path='{+old_object_uri}')
@action('heaserver-activity-desktopobjectaction-get-new-object-uri', rel='hea-desktop-object', itemif='new_object_uri is not None', path='{+new_object_uri}')
@action('heaserver-activity-desktopobjectaction-get-self', rel='self', path='/desktopobjectactions/{id}')
async def get_all_desktop_object_actions(request: web.Request) -> web.Response:
    """
    Gets all desktop object actions.
    :param request: the HTTP request.
    :return: all desktop object actions.
    ---
    summary: All desktop object actions.
    tags:
        - heaserver-activity
    responses:
      '200':
        $ref: '#/components/responses/200'
    """
    return await mongoservicelib.get_all(request, MONGODB_DESKTOP_OBJECT_ACTION_COLLECTION)


async def desktop_object_action_cb(app: web.Application, desktop_object: DesktopObject):
    """
    Message body callback for activities received from the message broker.

    :param app: the aiohttp Application (required).
    :param desktop_object: the DesktopObject (required).
    :raises ValueError: if the activity could not be inserted into MongoDB.
    """
    if await app[appproperty.HEA_DB].insert(desktop_object, MONGODB_DESKTOP_OBJECT_ACTION_COLLECTION) is None:
        raise ValueError(f'Failed to insert desktop object action on {desktop_object}')


def main() -> None:
    config = init_cmd_line(description='A service for tracking activity in hea',
                           default_port=8080)
    start(db=mongo.MongoManager, wstl_builder_factory=builder_factory(__package__), config=config,
          cleanup_ctx=[subscriber_cleanup_context_factory(message_body_cb=desktop_object_action_cb, config=config,
                                                          topics=[DesktopObjectAction.get_type_name()])])
