from enum import Enum
from typing import Optional

from .exceptions import (
    InvalidData,
    InvalidNotification,
    InvalidReceiver,
    InvalidThrottlePolicies,
)


class PushAction(Enum):
    MORDA = "morda"
    URI = "uri"


class Receiver:
    def __init__(
        self,
        *,
        uuid: str = None,
        did: str = None,
        uid: str = None,
        tag: str = None,
        yt: str = None,
    ):
        """
        :param uuid: Уникальный идентификатор установки приложения в AppMetrica.
        :param did:  Уникальный идентификатор устройства в AppMetrica.
        :param uid:  Уникальный идентификатор пользователя в Яндекс.Паспорте.
        :param tag:  Теговое выражение описывающее группу пользователей.
        :param yt:   Путь к YT-таблице, содержащей список iid.
        """
        if len([param for param in [uuid, did, uid, tag, yt] if param]) != 1:
            raise InvalidReceiver(
                "At least one receiver parameter should be passed but no more than one."
            )

        self.uuid = uuid
        self.did = did
        self.uid = uid
        self.tag = tag
        self.yt = yt

    def __str__(self):
        if self.uuid:
            return f"uuid: {self.uuid}"
        elif self.did:
            return f"did: {self.did}"
        elif self.uid:
            return f"uid: {self.uid}"
        elif self.tag:
            return f"tag: {self.tag}"
        elif self.yt:
            return f"yt: {self.yt}"

    def __eq__(self, other: "Receiver"):
        if not isinstance(other, Receiver):
            return False

        return (
            self.uuid == other.uuid
            and self.did == other.did
            and self.uid == other.uid
            and self.tag == other.tag
            and self.yt == other.yt
        )


class Notification:
    def __init__(
        self,
        *,
        title: str = None,
        body: str = None,
        icon: str = None,
        iconId: str = None,
        link: str = None,
    ):
        if not any([title, body, icon, iconId, link]):
            raise InvalidNotification(
                "At least one notification parameter should be passed"
            )

        self.title = title
        self.body = body
        self.icon = icon
        self.iconId = iconId
        self.link = link

    def to_dict(self):
        data = dict()
        if self.title:
            data["title"] = self.title
        if self.body:
            data["body"] = self.body
        if self.icon:
            data["icon"] = self.icon
        if self.iconId:
            data["iconId"] = self.iconId
        if self.link:
            data["link"] = self.link

        return data


class Data:
    def __init__(
        self,
        push_id: str,
        transit_id: str = None,
        content_id: str = None,
        stat_id: str = None,
        push_uri: str = None,
        push_action: PushAction = None,
        **kwargs,
    ):
        if not push_id:
            raise InvalidData("Push_id is required.")

        if push_action == PushAction.URI and not push_uri:
            raise InvalidData("Uri is not specified.")

        self.push_id = push_id
        self.transit_id = transit_id
        self.content_id = content_id
        self.stat_id = stat_id
        self.push_uri = push_uri
        self.push_action = push_action
        self.extra_params = kwargs

    def to_dict(self):
        data = dict()
        if self.push_id:
            data["push_id"] = self.push_id
        if self.transit_id:
            data["transit_id"] = self.transit_id
        if self.content_id:
            data["content_id"] = self.content_id
        if self.stat_id:
            data["stat_id"] = self.stat_id
        if self.push_uri:
            data["push_uri"] = self.push_uri
        if self.push_action:
            data["push_action"] = self.push_action.value
        if self.extra_params:
            data.update(self.extra_params)

        return data


class ThrottlePolicies:
    def __init__(
        self,
        install_id: Optional[str] = None,
        device_id: Optional[str] = None,
        content_id: Optional[str] = None,
    ):
        """
        :param install_id: Идентификатор лимита уведомлений при адресации по uuid.
        :param device_id:  Идентификатор лимита уведомлений при адресации по did.
        :param content_id: Идентификатор лимита уведомлений при адресации по
                           идентификатору контента.
        """
        if not any([install_id, device_id, content_id]):
            raise InvalidThrottlePolicies("At least one policy parameter must be set.")

        self.install_id = install_id
        self.device_id = device_id
        self.content_id = content_id

    def to_dict(self) -> dict:
        data = dict()
        if self.install_id:
            data["install_id"] = self.install_id
        if self.device_id:
            data["device_id"] = self.device_id
        if self.content_id:
            data["content_id"] = self.content_id

        return data
