from fb.models import Author, RemoteAuthor, RemoteServer
from fb.domain.models import DomainAuthor
from fb.api.api_utils import RequestContext
from fb.services.remote_server_service import RemoteServerService
from fb.services.post_service import PostService
import json


def get_author_service(request):
    """
    exposes the Author service for calls from the frontend

    """
    return AuthorService(RequestContext(request))


class AuthorService:
    """
    returns author information based on author id as defined in models.py

    :params :author_id
    """
    request_params = {
        "query", "author", "friend"
    }

    author_params = {
        "id", "host", "displayName", "url"
    }

    search_params = {
        "query", "author", "authors"
    }

    def __init__(self, context):
        self.context = context

    def get_author(self, author_id):
        author = self.get_local_author(author_id)
        if author:
            return author
        return self.get_remote_author_v2(author_id)

    def get_local_author(self, author_id):
        try:
            return DomainAuthor.from_author(
                self.get_author_model(author_id), self.context)
        except:
            return None

    def get_remote_author_v2(self, author_id):
        post_service = PostService(self.context)
        posts = post_service.get_all_for_user()

        all_authors = []
        all_authors += [c["author"] for p in posts for c in p["comments"]]
        all_authors += [p["author"] for p in posts]

        matches = [DomainAuthor(a) for a in all_authors if DomainAuthor(a).id() == author_id]

        return matches[0] if matches else None

    def update(self, author):
        author_id = author.pop("id")
        a = Author.objects.get(id=author_id)

        if "firstName" in author:
            user = a.user
            user.first_name = author["firstName"]
            user.save()

        if "lastName" in author:
            user = a.user
            user.last_name = author["lastName"]
            user.save()

        if "github" in author:
            a.github_username = author["github"]

        a.save()

        return DomainAuthor.from_author(a, self.context)

    def get_author_model(self, author_id):
        return Author.objects.get(id=author_id)

    def get_remote_author_model(self, author_id, service):
        return RemoteAuthor.objects.get(author_id=author_id, remote_server=service)

    def get_remote_author_model_by_id(self, author_id):
        return RemoteAuthor.objects.get(author_id=author_id)

    def get_friend_urls(self, author_id):
        author = None
        try:
            author = self.get_author_model(author_id)
        except:
            return None

        friends = []
        local_friends = author.friends.all()
        remote_friends = author.remote_friends.all()

        for friend in local_friends:
            friends.append(DomainAuthor.from_author(friend, self.context)["url"])
        for friend in remote_friends:
            friends.append(friend.get_endpoint_url())

        return friends

    def is_local_friends(self, author1_id, author2_id):
        author1 = None
        author2 = None
        friends = True
        following = True
        # get author 1
        try:
            author1 = self.get_author_model(author1_id)
        except Author.DoesNotExist:
            return None

        # get author2
        try:
            author2 = self.get_author_model(author2_id)
        except Author.DoesNotExist:
            return None

        try:
            author1.friends.get(id=author2_id)
        except Author.DoesNotExist:
            friends = False

        try:
            author1.following.get(id=author2_id)
        except Author.DoesNotExist:
            following = False

        return [
            DomainAuthor.build_author_url(author1.id, self.context),
            DomainAuthor.build_author_url(author2.id, self.context)], friends,\
            following

    def is_remote_friends(self, author1_id, author2_id):
        author1 = None
        author2 = None
        friends = True
        following = True
        server = None
        # get author 1
        try:
            author1 = self.get_author_model(author1_id)
        except Author.DoesNotExist:
            return None

        # get author2
        try:
            author2 = self.get_remote_author_v2(author2_id)
        except RemoteAuthor.DoesNotExist:
            friends = False
            following = False

        if author2 is not None:
            try:
                author1.remote_friends.get(author_id=author2.id())
            except RemoteAuthor.DoesNotExist:
                friends = False
            try:
                author1.remote_following.get(author_id=author2.id())
            except RemoteAuthor.DoesNotExist: