// ==========================================================================
// Author:  Yee Hsu
// Date:    6/12/2010
//
// Desc:    Facebook API connector. Allows developer to connect to
//          Facebook and perform certain Facebook operations to user
//          profiles. Exposes certain social API for easy publishing.
// ==========================================================================

#include "StdAfx.h"
#include "Facebook.h"

Facebook::Facebook()
{
    m_graph_url     = "https://graph.facebook.com/";
    m_access_token  = "121054341253966|1ed5a6d37cc6c45f0fb9feea-100001151298397|N91Bphh7SIMJp7xVkm74v4iRpEQ";
}

Facebook::~Facebook()
{}

bool Facebook::GetFriendList(const string& id, FacebookFriendList& list) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/friends?access_token=" + m_access_token;

    if (http.Request(task))
    {
        JsonArray jarr;
        JsonObject job = JsonObject(Json(task.resp_content));

        if (job.Get("data", jarr))
        {
            list.clear();

            for (unsigned int i = 0; i < jarr.Size(); ++i)
            {
                JsonObject item;
                jarr.Get(i, item);

                FacebookUser _datum(item);
                list.push_back(_datum);
            }
            return true;
        }
    }
    return false;
}

bool Facebook::LikePost( const string& id ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/likes?access_token=" + m_access_token;

    if (http.PostRequest(task))
    {
        if (task.resp_content.compare("true") == 0)
            return true;
    }
    return false;
}

bool Facebook::GetProfile( const string& id, FacebookProfile& profile ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "?access_token=" + m_access_token;

    if (http.Request(task))
    {
        FacebookProfile _datum = JsonObject(Json(task.resp_content));;
        profile = _datum;
        return true;
    }
    return false;
}

bool Facebook::GetComments( const string& id, FacebookPostCommentList& list ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/comments?access_token=" + m_access_token;

    if (http.Request(task))
    {
        JsonArray jarr;
        JsonObject job = JsonObject(Json(task.resp_content));

        if (job.Get("data", jarr))
        {
            list.clear();

            for (unsigned int i = 0; i < jarr.Size(); ++i)
            {
                JsonObject item;
                jarr.Get(i, item);

                FacebookPostComment _datum(item);
                list.push_back(_datum);
            }
            return true;
        }
    }
    return false;
}

bool Facebook::GetPost( const string& id, FacebookPost& post ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "?&access_token=" + m_access_token;

    if (http.Request(task))
    {
        FacebookPost _datum = JsonObject(Json(task.resp_content));
        post = _datum;
        return true;
    }
    return false;
}

bool Facebook::GetStatus( const string& id, FacebookPost& post ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/statuses?limit=1&access_token=" + m_access_token;

    if (http.Request(task))
    {
        JsonArray jarr;
        JsonObject job = JsonObject(Json(task.resp_content));

        if (job.Get("data", jarr))
        {
            JsonObject item;
            jarr.Get(0, item);
            post = item;
            return true;
        }
    }
    return false;
}

bool Facebook::GetLikers( const string& id, FacebookLikerList& list ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/likes?access_token=" + m_access_token;

    if (http.Request(task))
    {
        JsonArray jarr;
        JsonObject job = JsonObject(Json(task.resp_content));

        if (job.Get("data", jarr))
        {
            list.clear();

            for (unsigned int i = 0; i < jarr.Size(); ++i)
            {
                JsonObject item;
                jarr.Get(i, item);

                FacebookUser _datum(item);
                list.push_back(_datum);
            }
            return true;
        }
    }
    return false;
}

bool Facebook::GetFeeds( FacebookPostList& list, const bool likes /*= false*/, const bool comments /*= false*/ ) const
{
    bool b = GetWall(list);

    for (FacebookPostList::iterator iter = list.begin(); iter != list.end(); ++iter)
    {
        // get all likers if there is any
        if (likes && iter->likes > 0)
        {
            this->GetLikers(iter->id, iter->likers);
        }

        // get all comments not shown on wall, that is, more than 5 comments
        if (comments && iter->count > 5)
        {
            this->GetComments(iter->id, iter->comments);
        }
    }
    return b;
}

bool Facebook::GetWall(FacebookPostList& list) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + "me/home?access_token=" + m_access_token;

    if (http.Request(task))
    {
        JsonArray jarr;
        JsonObject job = JsonObject(Json(task.resp_content));

        if (job.Get("data", jarr))
        {
            list.clear();

            for (unsigned int i = 0; i < jarr.Size(); ++i)
            {
                JsonObject item;
                jarr.Get(i, item);

                FacebookPost _datum(item);
                list.push_back(_datum);
            }
            return true;
        }
    }
    return false;
}

bool Facebook::PostComment(const string& id, const string& str, OUT string& pid) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + id + "/comments";

    task.AddPostFieldParam("access_token", m_access_token);
    task.AddPostFieldParam("message", str);

    if (http.Request(task))
    {
        JsonObject job = JsonObject(Json(task.resp_content));     

        if (job.Get("id", pid))
            return true;
    }
    return false;
}

bool Facebook::PostNote( const FacebookNotePost& post, OUT string& pid ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + "me/notes";

    task.AddPostFieldParam( "access_token", m_access_token );
    task.AddPostFieldParam( "subject", post.subject );
    task.AddPostFieldParam( "message", post.message );

    if (http.Request(task))
    {
        JsonObject job = JsonObject(Json(task.resp_content));    

        if (job.Get("id", pid))
            return true;
    }
    return false;
}

bool Facebook::PostLink( const FacebookLinkPost& post, OUT string& pid ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + "me/feed";

    task.AddPostFieldParam( "access_token", m_access_token );
    task.AddPostFieldParam( "message", post.message );
    task.AddPostFieldParam( "link", post.link );
    task.AddPostFieldParam( "picture", post.picture );
    task.AddPostFieldParam( "name", post.name );
    task.AddPostFieldParam( "caption", post.caption );
    task.AddPostFieldParam( "description", post.description );

    if (http.Request(task))
    {
        JsonObject job = JsonObject(Json(task.resp_content));     

        if (job.Get("id", pid))
            return true;
    }
    return false;
}

bool Facebook::PostStatus( const string& str, OUT string& pid ) const
{
    FacebookLinkPost post;
    post.message = str;

    return this->PostLink(post, pid);
}

bool Facebook::IsConnected() const
{
    DownloadTask task;
    HttpClient http;

    task.url = "http://www.facebook.com/connect/login_success.html";

    if (http.Request(task))
    {
        return true;
    }
    return false;
}

bool Facebook::CreateEvent( const FacebookEventPost& post, OUT string& pid ) const
{
    DownloadTask task;
    HttpClient http;

    task.url = m_graph_url + "me/events";

    task.AddPostFieldParam( "access_token", m_access_token );
    task.AddPostFieldParam( "name", post.name );
    task.AddPostFieldParam( "start_time", post.start_time );
    task.AddPostFieldParam( "end_time", post.end_time );

    if (http.Request(task))
    {
        JsonObject job = JsonObject(Json(task.resp_content));  

        if (job.Get("id", pid))
            return true;
    }
    return false;
}

bool Facebook::ReplyEvent( const string &id, const FacebookEventPost::EventResponse& res ) const
{
    // TO DO.....

    switch (res)
    {
        case FacebookEventPost::ATTEND:
            break;

        case FacebookEventPost::MAYBE:
            break;

        case FacebookEventPost::DECLINE:
            break;

        default:
            break;
    }
    return false;
}