"""
Common utility methods and decorators for Social Facebook APIs.
"""
import json
import urllib2
import facebook
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import status
from rest_framework.response import Response
from social.apps.django_app.default.models import UserSocialAuth
from openedx.core.djangoapps.user_api.models import UserPreference
from student.models import User


# TODO
# The pagination strategy needs to be further flushed out.
# What is the default page size for the facebook Graph API? 25? Is the page size a parameter that can be tweaked?
# If a user has a large number of friends, we would be calling the FB API num_friends/page_size times.
#
# However, on the app, we don't plan to display all those friends anyway.
# If we do, for scalability, the endpoints themselves would need to be paginated.
def get_pagination(friends):
    """
    Get paginated data from FaceBook response
    """
    data = friends['data']
    while 'paging' in friends and 'next' in friends['paging']:
        response = urllib2.urlopen(friends['paging']['next'])
        friends = json.loads(response.read())
        data = data + friends['data']
    return data


def get_friends_from_facebook(serializer):
    """
    Return a list with the result of a facebook /me/friends call
    using the oauth_token contained within the serializer object.
    If facebook returns an error, return a response object containing
    the error message.
    """
    try:
        graph = facebook.GraphAPI(serializer.object['oauth_token'])
        friends = graph.request(settings.FACEBOOK_API_VERSION + "/me/friends")
        return get_pagination(friends)
    except facebook.GraphAPIError, ex:
        return Response({'error': ex.result['error']['message']}, status=status.HTTP_400_BAD_REQUEST)


def get_linked_edx_accounts(data):
    """
    Return a list of friends from the input that are edx users with the
    additional attributes of edX_id and edX_username
    """
    friends_that_are_edx_users = []
    for friend in data:
        query_set = UserSocialAuth.objects.filter(uid=unicode(friend['id']))
        if query_set.count() == 1:
            friend['edX_id'] = query_set[0].user_id
            friend['edX_username'] = query_set[0].user.username
            friends_that_are_edx_users.append(friend)
    return friends_that_are_edx_users


def share_with_facebook_friends(friend):
    """
    Return true if the user's share_with_facebook_friends preference is set to true.
    """

    # Calling UserPreference directly because the requesting user may be different (and not is_staff).
    try:
        existing_user = User.objects.get(username=friend['edX_username'])
    except ObjectDoesNotExist:
        return False

    return UserPreference.get_value(existing_user, 'share_with_facebook_friends') == 'True'
