###############################################################################
# This file holds the implementations for all the API clients.
#
# If you want to develop a new client, here are some suggestions: Get the fetch
# methods working first, then the push, then the liquidsoap notifier.  You will
# probably want to create a script on your server side to automatically
# schedule a playlist one minute from the current time.
###############################################################################
import logging
import sys
from datetime import datetime, timedelta

from configobj import ConfigObj
from dateutil.parser import isoparse

from .utils import RequestProvider, fromisoformat, time_in_milliseconds, time_in_seconds

LIBRETIME_API_VERSION = "2.0"

api_config = {}
api_endpoints = {}

api_endpoints["version_url"] = "version/"
api_endpoints["schedule_url"] = "schedule/"
api_endpoints["webstream_url"] = "webstreams/{id}/"
api_endpoints["show_instance_url"] = "show-instances/{id}/"
api_endpoints["show_url"] = "shows/{id}/"
api_endpoints["file_url"] = "files/{id}/"
api_endpoints["file_download_url"] = "files/{id}/download/"
api_config["api_base"] = "api/v2"


class AirtimeApiClient:
    def __init__(self, logger=None, config_path="/etc/airtime/airtime.conf"):
        if logger is None:
            self.logger = logging
        else:
            self.logger = logger

        try:
            self.config = ConfigObj(config_path)
            self.config.update(api_config)
            self.services = RequestProvider(self.config, api_endpoints)
        except Exception as e:
            self.logger.exception("Error loading config file: %s", config_path)
            sys.exit(1)

    def get_schedule(self):
        current_time = datetime.utcnow()
        end_time = current_time + timedelta(days=1)

        str_current = current_time.isoformat(timespec="seconds")
        str_end = end_time.isoformat(timespec="seconds")
        data = self.services.schedule_url(
            params={
                "ends__range": ("{}Z,{}Z".format(str_current, str_end)),
                "is_valid": True,
                "playout_status__gt": 0,
            }
        )
        result = {"media": {}}
        for item in data:
            start = isoparse(item["starts"])
            key = start.strftime("%Y-%m-%d-%H-%M-%S")
            end = isoparse(item["ends"])

            show_instance = self.services.show_instance_url(id=item["instance_id"])
            show = self.services.show_url(id=show_instance["show_id"])

            result["media"][key] = {
                "start": start.strftime("%Y-%m-%d-%H-%M-%S"),
                "end": end.strftime("%Y-%m-%d-%H-%M-%S"),
                "row_id": item["id"],
                "show_name": show["name"],
            }
            current = result["media"][key]
            if item["file"]:
                current["independent_event"] = False
                current["type"] = "file"
                current["id"] = item["file_id"]

                fade_in = time_in_milliseconds(fromisoformat(item["fade_in"]))
                fade_out = time_in_milliseconds(fromisoformat(item["fade_out"]))

                cue_in = time_in_seconds(fromisoformat(item["cue_in"]))
                cue_out = time_in_seconds(fromisoformat(item["cue_out"]))

                current["fade_in"] = fade_in
                current["fade_out"] = fade_out
                current["cue_in"] = cue_in
                current["cue_out"] = cue_out

                info = self.services.file_url(id=item["file_id"])
                current["metadata"] = info
                current["uri"] = item["file"]
                current["replay_gain"] = info["replay_gain"]
                current["filesize"] = info["filesize"]
            elif item["stream"]:
                current["independent_event"] = True
                current["id"] = item["stream_id"]
                info = self.services.webstream_url(id=item["stream_id"])
                current["uri"] = info["url"]
                current["type"] = "stream_buffer_start"
                # Stream events are instantaneous
                current["end"] = current["start"]

                result["{}_0".format(key)] = {
                    "id": current["id"],
                    "type": "stream_output_start",
                    "start": current["start"],
                    "end": current["start"],
                    "uri": current["uri"],
                    "row_id": current["row_id"],
                    "independent_event": current["independent_event"],
                }

                result[end.isoformat()] = {
                    "type": "stream_buffer_end",
                    "start": current["end"],
                    "end": current["end"],
                    "uri": current["uri"],
                    "row_id": current["row_id"],
                    "independent_event": current["independent_event"],
                }

                result["{}_0".format(end.isoformat())] = {
                    "type": "stream_output_end",
                    "start": current["end"],
                    "end": current["end"],
                    "uri": current["uri"],
                    "row_id": current["row_id"],
                    "independent_event": current["independent_event"],
                }
        return result

    def update_file(self, file_id, payload):
        data = self.services.file_url(id=file_id)
        data.update(payload)
        return self.services.file_url(id=file_id, _put_data=data)