from twitch.api.base import TwitchAPI
from twitch.constants import (
    DIRECTION_DESC,
    DIRECTIONS,
    MAX_FOLLOWS_LIMIT,
    USERS_SORT_BY,
    USERS_SORT_BY_CREATED_AT,
)
from twitch.decorators import oauth_required
from twitch.exceptions import TwitchAttributeException
from twitch.resources import Follow, Subscription, User, UserBlock


class Users(TwitchAPI):
    @oauth_required
    def get(self):
        response = self._request_get("user")
        return User.construct_from(response)

    def get_by_id(self, user_id):
        response = self._request_get("users/{}".format(user_id))
        return User.construct_from(response)

    @oauth_required
    def get_emotes(self, user_id):
        response = self._request_get("users/{}/emotes".format(user_id))
        return response["emoticon_sets"]

    @oauth_required
    def check_subscribed_to_channel(self, user_id, channel_id):
        response = self._request_get(
            "users/{}/subscriptions/{}".format(user_id, channel_id)
        )
        return Subscription.construct_from(response)

    def get_all_follows(
        self, user_id, direction=DIRECTION_DESC, sort_by=USERS_SORT_BY_CREATED_AT
    ):
        if direction not in DIRECTIONS:
            raise TwitchAttributeException(
                "Direction is not valid. Valid values are {}".format(DIRECTIONS)
            )
        if sort_by not in USERS_SORT_BY:
            raise TwitchAttributeException(
                "Sort by is not valid. Valid values are {}".format(USERS_SORT_BY)
            )
        offset = 0
        params = {"limit": MAX_FOLLOWS_LIMIT, "direction": direction}
        follows = []
        while offset is not None:
            params.update({"offset": offset})
            response = self._request_get(
                "users/{}/follows/channels".format(user_id), params=params
            )
            offset = response.get("_offset")
            follows.extend(response["follows"])
        return [Follow.construct_from(x) for x in follows]

    def get_follows(
        self,
        user_id,
        limit=25,
        offset=0,
        direction=DIRECTION_DESC,
        sort_by=USERS_SORT_BY_CREATED_AT,
    ):
        if limit > MAX_FOLLOWS_LIMIT:
            raise TwitchAttributeException(
                "Maximum number of objects returned in one request is 100"
            )
        if direction not in DIRECTIONS:
            raise TwitchAttributeException(
                "Direction is not valid. Valid values are {}".format(DIRECTIONS)
            )
        if sort_by not in USERS_SORT_BY:
            raise TwitchAttributeException(
                "Sort by is not valid. Valid values are {}".format(USERS_SORT_BY)
            )
        params = {"limit": limit, "offset": offset, "direction": direction}
        response = self._request_get(
            "users/{}/follows/channels".format(user_id), params=params
        )
        return [Follow.construct_from(x) for x in response["follows"]]

    def check_follows_channel(self, user_id, channel_id):
        response = self._request_get(
            "users/{}/follows/channels/{}".format(user_id, channel_id)
        )
        return Follow.construct_from(response)

    @oauth_required
    def follow_channel(self, user_id, channel_id, notifications=False):
        data = {"notifications": notifications}
        response = self._request_put(
            "users/{}/follows/channels/{}".format(user_id, channel_id), data
        )
        return Follow.construct_from(response)

    @oauth_required
    def unfollow_channel(self, user_id, channel_id):
        self._request_delete("users/{}/follows/channels/{}".format(user_id, channel_id))

    @oauth_required
    def get_user_block_list(self, user_id, limit=25, offset=0):
        if limit > 100:
            raise TwitchAttributeException(
                "Maximum number of objects returned in one request is 100"
            )

        params = {"limit": limit, "offset": offset}
        response = self._request_get("users/{}/blocks".format(user_id), params=params)
        return [UserBlock.construct_from(x) for x in response["blocks"]]

    @oauth_required
    def block_user(self, user_id, blocked_user_id):
        response = self._request_put(
            "users/{}/blocks/{}".format(user_id, blocked_user_id)
        )
        return UserBlock.construct_from(response)

    @oauth_required
    def unblock_user(self, user_id, blocked_user_id):
        self._request_delete("users/{}/blocks/{}".format(user_id, blocked_user_id))

    def translate_usernames_to_ids(self, usernames):
        if isinstance(usernames, list):
            usernames = ",".join(usernames)

        response = self._request_get("users?login={}".format(usernames))
        return [User.construct_from(x) for x in response["users"]]
