// twister_actions.js
// 2013 Miguel Freitas
//
// This file contains some twister "actions" like requesting
// posts from dht, sending posts, replies. It seems to be a
// intermediate layer between twister_io and interface, but
// separation is not clearly defined. Perhaps it would be better
// to get rid of this file altogether.

// global variables

var postsPerRefresh = 10;
var maxExpandPost = 8;
var maxExpandPostTop = 4;
var _hashtagProcessedMap = {};
var _hashtagPendingPosts = [];
var autoUpdateHashtag = false;

// ----------------

function requestRepliedBefore(postLi)
{
    if(postLi.siblings().length >= maxExpandPostTop)
        return;

    var originalPost = postLi.find(".post-data");
    var reply_n = originalPost.attr('data-replied-to-screen-name');
    var reply_k = originalPost.attr('data-replied-to-id');

    if( reply_n != undefined && reply_k != undefined ) {
        dhtget( reply_n, "post" + reply_k, "s",
               function(postLi, postFromJson) {
                   var newStreamPost = postToElem(postFromJson, "related");
                   newStreamPost.hide();
                   postLi.before(newStreamPost);
                   newStreamPost.slideDown("fast");
                   $.MAL.relatedPostLoaded();
                   requestRepliedBefore(newStreamPost);
               }, postLi);
    }
}

function requestRepliesAfter(postLi)
{
    if($.MAL.getExpandedPostsCount(postLi) >= maxExpandPost)
        return;

    var originalPost = postLi.find(".post-data");
    var original_n = originalPost.attr('data-screen-name');
    var original_k = originalPost.attr('data-id');

    if( original_n != undefined && original_k != undefined ) {
        dhtget( original_n, "replies" + original_k, "m", $.MAL.reqRepAfterCB, postLi);
    }
}

function getTopPostOfConversation(postLi, post, postboard) {
    var reply_n;
    var reply_k;

    if (post && typeof(post) !== 'undefined' && "reply" in post["userpost"]) {
        reply_k = post["userpost"]["reply"]["k"];
        reply_n = post["userpost"]["reply"]["n"];
    } else if (postLi && typeof(postLi) !== 'undefined') {
        var originalPost = postLi.find(".post-data");
        reply_n = originalPost.attr('data-replied-to-screen-name');
        reply_k = originalPost.attr('data-replied-to-id');
    }

    if( reply_n != undefined && reply_k != undefined ) {
        dhtget( reply_n, "post" + reply_k, "s",
            function(postLi, postFromJson) {
                getTopPostOfConversation(null, postFromJson, postboard);
            }, postLi);
    } else {
        var newStreamPost;
        if (post)
            newStreamPost = postToElem(post, "related");
        else {
            newStreamPost = postLi.clone(true);
            newStreamPost.removeClass('original');
            newStreamPost.addClass('related');
            newStreamPost.find('.expanded-content').hide();
            newStreamPost.find('.show-more').hide();
        }
        requestRepliesAfterAll(newStreamPost);
        newStreamPost.find('.post-expand').remove();
        newStreamPost.unbind('click');
        newStreamPost.hide();
        postboard.append(newStreamPost);
        newStreamPost.slideDown("fast");
    }
}

function requestRepliesAfterAll(postLi)
{
    var originalPost = postLi.find(".post-data");
    var original_n = originalPost.attr('data-screen-name');
    var original_k = originalPost.attr('data-id');

    if( original_n != undefined && original_k != undefined ) {
        dhtget( original_n, "replies" + original_k, "m", $.MAL.reqRepAfterCB, postLi);
    }
}

function requestRTs(postLi)
{
    var originalPost = postLi.find(".post-data");

    var original_n = originalPost.attr('data-screen-name');
    var original_k = originalPost.attr('data-id');

    if( original_n != undefined && original_k != undefined ) {
        dhtget( original_n, "rts" + original_k, "m",
               function(originalPost, postsFromJson) {

                    if( postsFromJson.length ) {
                        var statCountValue = originalPost.find(".stat-count-value");
                        statCountValue.text( postsFromJson.length );

                        var avatarRow = originalPost.find(".avatar-row");
                        avatarRow.empty();
                        for( var i = 0; i < postsFromJson.length && i < 8; i++) {
                            var n = postsFromJson[i]["userpost"]["n"];
                            var elemUser = $("#avatar-row-template").clone(true);
                            elemUser.removeAttr('id');
                            elemUser.attr('href',$.MAL.userUrl(n));
                            getFullname(n,elemUser.find(".user-name-tooltip"));
                            getAvatar(n,elemUser.find(".size24"));
                            avatarRow.append( elemUser );
                        }

                        originalPost.find(".post-stats").slideDown("fast");
                    }
               }, originalPost);
    }
}

function appendPostToContainer(postFromJson, containerToAppend)
{
    var newStreamPost = postToElem(postFromJson, "original");
    newStreamPost.hide();
    containerToAppend.append( newStreamPost );
    newStreamPost.slideDown("fast");
    $.MAL.postboardLoaded();
}

var profilePostsLoading = false;

function requestPost(containerToAppend,username,resource,cbFunc,cbArgs){

    console.log('dhtget '+username+' '+resource);

    dhtget( username, resource, "s",
        function(args, postFromJson) {
            if( postFromJson ) {

            console.log(postFromJson);

            appendPostToContainer(postFromJson,args.containerToAppend);
                
            if(args.cbFunc!=undefined) args.cbFunc(args.cbArgs);
               
            } 
        }, 
        {containerToAppend:containerToAppend,cbFunc:cbFunc,cbArgs:cbArgs} 
    );

}

function requestPostRecursively(containerToAppend,username,resource,count,useGetposts)
{
    var max_id = -1;
    if( !resource ) {
        var streamItems = containerToAppend.children();
        if( streamItems.length != 0 ) {
            var lastItem = streamItems.eq(streamItems.length-1);
            resource = "post" + lastItem.find(".post-data").attr("data-lastk");
            max_id = parseInt(lastItem.find(".post-data").attr("data-id"))-1;
        }
    }

    profilePostsLoading = true;
    
    if( useGetposts ) {
        req = {username: username}
        if( max_id != -1 ) {
            req.max_id = max_id;
        }

        twisterRpc("getposts", [count,[req]],
                       function(args, posts) {
                           for( var i = 0; i < posts.length; i++ ) {
                              appendPostToContainer(posts[i],args.containerToAppend);
                           }
                           profilePostsLoading = false;
                       }, {containerToAppend:containerToAppend},
                       function(args, ret) {
                           profilePostsLoading = false;
                       }, {});
    } else {
        dhtget( username, resource, "s",
            function(args, postFromJson) {
               if( postFromJson ) {
                   appendPostToContainer(postFromJson,args.containerToAppend);

                   if( args.count > 1 ) {
                       var userpost = postFromJson["userpost"];
                       var n = userpost["n"];
                       var lastk = userpost["lastk"];
                       if( lastk == undefined )
                           lastk = userpost["k"] - 1; // not true with directmsgs in stream

                       requestPostRecursively(args.containerToAppend, n, "post"+lastk, count-1);
                   } else {
                       profilePostsLoading = false;
                       args.containerToAppend.scroll();
                   }
               } else {
                   profilePostsLoading = false;
               }
           }, {containerToAppend:containerToAppend, count:count} );
    }
}


function newPostMsg(msg, $postOrig) {
    if( lastPostId != undefined ) {
        var params = [defaultScreenName, lastPostId + 1, msg]
        if( $postOrig.length ) {
            params.push($postOrig.attr('data-screen-name'));
            params.push(parseInt($postOrig.attr('data-id')));
        }
        twisterRpc("newpostmsg", params,
                   function(arg, ret) { incLastPostId(); }, null,
                   function(arg, ret) { var msg = ("message" in ret) ? ret.message : ret;
                                        alert(polyglot.t("ajax_error", { error: msg })); }, null);
    } else {
        alert(polyglot.t("Internal error: lastPostId unknown (following yourself may fix!)"));
    }
}

function newRtMsg($postOrig) {
    var content_to_rt = $postOrig.attr('data-content_to_rt');
    var content_to_sigrt = $postOrig.attr('data-content_to_sigrt');

    var sig_userpost = String(content_to_sigrt);
    var userpost = $.evalJSON(String(content_to_rt));
    var rtObj = { sig_userpost :sig_userpost, userpost : userpost };

    if( lastPostId != undefined ) {
        var params = [defaultScreenName, lastPostId+1, rtObj]

        twisterRpc("newrtmsg", params,
                   function(arg, ret) { incLastPostId(); }, null,
                   function(arg, ret) { var msg = ("message" in ret) ? ret.message : ret;
                                        alert(polyglot.t("ajax_error", { error: msg })); }, null);
    } else {
        alert(polyglot.t("Internal error: lastPostId unknown (following yourself may fix!)"));
    }
}


function updateProfileData(profileModalContent, username) {

    //profileModalContent.find("a").attr("href",$.MAL.userUrl(username));
    profileModalContent.filter(".profile-card").attr("data-screen-name", username);
    profileModalContent.find(".profile-screen-name b").text(username);
    profileModalContent.find("a.follow").attr("href", $.MAL.followUrl(username));
    profileModalContent.find("a.direct-messages-with-user").attr("href", $.MAL.dmchatUrl(username));
    profileModalContent.find("a.new-post-to").attr("href", $.MAL.newPostToUrl(username));
    profileModalContent.find("a.mentions-from-user").attr("href", $.MAL.mentionsUrl(username));
    getFullname( username, profileModalContent.find(".profile-name") );
    getLocation( username, profileModalContent.find(".profile-location") );
    getWebpage( username, profileModalContent.find(".profile-url") );
    getBio( username, profileModalContent.find(".profile-bio") );
    getTox( username, profileModalContent.find(".profile-tox") );
    getBitmessage( username, profileModalContent.find(".profile-bitmessage") );
    getAvatar( username, profileModalContent.find(".profile-card-photo") );
    getPostsCount( username,  profileModalContent.find(".posts-count") );
    getFollowers( username, profileModalContent.find(".followers-count") );
    getNumFollowing( username, profileModalContent.find(".following-count") );
    getWhoFollows ( username, profileModalContent.find(".who-follow") );
    
    profileModalContent.find(".following-count").parent().attr("href", $.MAL.followingUrl(username));

    var postsView = profileModalContent.find(".postboard-posts");
    
    // try using getposts first. fallback to dht.
    twisterRpc("getposts", [1,[{username: username}]],
                       function(args, posts) {
                           updateProfilePosts(postsView, username, posts.length);
                       }, {},
                       function(args, ret) {
                           updateProfilePosts(postsView, username, false);
                       }, {});
}

function updateProfilePosts(postsView, username, useGetposts) {
    requestPostRecursively(postsView,username,"status",postsPerRefresh, useGetposts);

    postsView.scroll(function(){
        if (!profilePostsLoading) {
            var $this = $(this);
            if ($this.scrollTop() >= this.scrollHeight - $this.height() - 20) {
                requestPostRecursively($this,username,"",postsPerRefresh, useGetposts);
            }
        }
     });
}

function updateFollowingData(followingModalContent, username) {
    followingModalContent.find(".following-screen-name b").text(username);
    loadFollowingIntoList( username, $(followingModalContent[1]) );
}

function clearHashtagProcessed() {
    _hashtagProcessedMap = {};
    _hashtagPendingPosts = [];
}

function requestHashtag(postboard,hashtag,resource, timeoutArgs) {
    dhtget( hashtag, resource, "m",
           function(args, data) {
               processHashtag(args.postboard, args.hashtag, data);
           }, {postboard:postboard,hashtag:hashtag}, 
           timeoutArgs);
}

function processHashtag(postboard, hashtag, data) {
    if( data && window.location.hash.indexOf(encodeURIComponent(hashtag)) != -1 ) {
        for( var i = data.length-1; i >= 0; i-- ) {
            var userpost = data[i]["userpost"];
            var key = userpost["n"] + ";" + userpost["time"];
            if( !(key in _hashtagProcessedMap) ) {
                _hashtagProcessedMap[key] = true;
                _hashtagPendingPosts.push(data[i]);
            }
        }
        
        if(!postboard.children().length && !_hashtagPendingPosts.length && hashtag != defaultScreenName)
            postboard.closest("div").find(".no-posts-found-message").show();

        if( _hashtagPendingPosts.length ) {
            if( !postboard.children().length || autoUpdateHashtag ) {
                displayHashtagPending(postboard);
            } else {
                var newTweetsBar = postboard.closest("div").find(".postboard-news");
                newTweetsBar.text(polyglot.t("new_posts", _hashtagPendingPosts.length));
                newTweetsBar.fadeIn("slow");
            }
            postboard.closest("div").find(".no-posts-found-message").hide();
        }
    }
}

function displayHashtagPending(postboard) {
    for( var i = 0; i < _hashtagPendingPosts.length; i++ ) {
        var streamPost = postToElem(_hashtagPendingPosts[i], "original");
        var timePost = _hashtagPendingPosts[i]["userpost"]["time"];

        var streamItems = postboard.children();
        if( streamItems.length == 0) {
            postboard.prepend( streamPost );
        } else {
            var j = 0;
            for( j = 0; j < streamItems.length; j++) {
                var streamItem = streamItems.eq(j);
                var timeItem = streamItem.attr("data-time");
                if( timeItem == undefined ||
                    timePost > parseInt(timeItem) ) {
                    // this post in stream is older, so post must be inserted above
                    streamItem.before(streamPost);
                    break;
                }
            }
            if( j == streamItems.length ) {
                postboard.append( streamPost );
            }
        }
    }
    $.MAL.postboardLoaded();
    _hashtagPendingPosts = [];
}