import connexion
from flask import current_app

from aura_engine_api.rest import util
from aura_engine_api.rest.models.clock_info import ClockInfo  # noqa: E501
from aura_engine_api.rest.models.health_log import HealthLog  # noqa: E501
from aura_engine_api.rest.models.play_log import PlayLog  # noqa: E501


def add_playlog(body):  # noqa: E501
    """Adds an entry to the playlog

    Stores the passed playlog entry in the local database. Also note, similar to the `ClockInfo` storage endpoint, this information is only stored to the database if a) it is a main node or b) if it's a sync node, and the `logSource` is the currently active engine.  # noqa: E501

    :param body:
    :type body: dict | bytes

    :rtype: None
    """
    if connexion.request.is_json:
        body = PlayLog.from_dict(connexion.request.get_json())  # noqa: E501
    service = current_app.config["SERVICE"]
    return service.store_playlog(body, connexion.request.get_json())


def clock_info():  # noqa: E501
    """Get all information to display the studio clock

    Retrieves the currently playing timeslot, its playlist and entries plus the next timeslot for being used by the studio clock.  # noqa: E501


    :rtype: ClockInfo
    """
    service = current_app.config["SERVICE"]
    return service.get_clock_info()


def get_active_source():  # noqa: E501
    """Get active play-out source (engine1, engine2)

    Retrieves the status entry of the currently active source (engine 1, 2 or other source)  # noqa: E501


    :rtype: int
    """
    service = current_app.config["SERVICE"]
    return service.get_active_source()


def get_report(year_month):  # noqa: E501
    """Report for one month

    Returns a report for the given month  # noqa: E501

    :param year_month: Month to create the report for in the format \"yyyy_mm\"
    :type year_month: str

    :rtype: List[PlayLog]
    """
    return "do some magic!"


def get_source_health(number):  # noqa: E501
    """Get most recent health info

    Retrieves the most recent health info of the requested engine  # noqa: E501

    :param number: Number of the engine
    :type number: int

    :rtype: HealthLog
    """
    service = current_app.config["SERVICE"]
    return service.get_source_health(number)


def list_playlog(
    from_date=None, to_date=None, page=None, limit=None, skip_synced=None
):  # noqa: E501
    """List tracks in the play-log since the given timestamp

    Get paginated playlog entries for since the given timestamp.  # noqa: E501

    :param from_date: Get entries after this timestamp
    :type from_date: str
    :param to_date: Get entries before this timestamp
    :type to_date: str
    :param page: The number of items to skip before starting to collect the result set
    :type page: int
    :param limit: The numbers of items to return per page
    :type limit: int
    :param skip_synced: If true only returns items which are in unsynced state on the main node
    :type skip_synced: bool

    :rtype: List[PlayLog]
    """
    service = current_app.config["SERVICE"]
    fd = None
    td = None

    if from_date is not None and to_date is not None:
        try:
            fd = util.deserialize_datetime(from_date)
            td = util.deserialize_datetime(to_date)
        except Exception:
            service.logger.warning(
                "Invalid 'from_date' (%s) or 'to_date' (%s) for 'list_playlog'"
                % (str(from_date), str(to_date))
            )

    return service.list_playlog(page, limit, fd, td, skip_synced)


def log_source_health(body, number):  # noqa: E501
    """Log health info

    Logs another health entry for the given engine  # noqa: E501

    :param body:
    :type body: dict | bytes
    :param number: Number of the engine
    :type number: int

    :rtype: None
    """
    if connexion.request.is_json:
        body = HealthLog.from_dict(connexion.request.get_json())  # noqa: E501
    service = current_app.config["SERVICE"]
    service.log_source_health(number, body, connexion.request.get_json())


def set_active_source(number):  # noqa: E501
    """Set active play-out source (engine1, engine2)

    Activates one engine and deactivates the other  # noqa: E501

    :param number: Number of the engine
    :type number: int

    :rtype: None
    """
    service = current_app.config["SERVICE"]
    return service.set_active_source(number)


def set_clock_info(body):  # noqa: E501
    """Set current studio clock information such as timeslot info and track-list for engine 1 or 2 within the Engine API database.

    Set current studio clock information (source, timeslot and planned track-list) and the next timeslot of the given play-out source (engine1, engine2). Please note, the `currentTrack` and `currentPlaylogs` information is ignored in the PUT request. It's only dynamically populated in the GET request by reading the most recent playlog. To store current track information use `/playlog` instead. Also note, similar to the `PlayLog` storage endpoint, this information is only stored to the database if a) it is a main node or b) if it's a sync node, and the `engineSource` is the currently active engine.  # noqa: E501

    :param body:
    :type body: dict | bytes

    :rtype: None
    """
    if connexion.request.is_json:
        body = ClockInfo.from_dict(connexion.request.get_json())  # noqa: E501
    service = current_app.config["SERVICE"]
    return service.set_clock_info(body, connexion.request.get_json())