////////////////////////////////////////////////////////
// Comments: single object created to manage the comment widget on the page
////////////////////////////////////////////////////////
//Includes Required: 
//  jquery-1.3.2.js
//  jquery.json-1.3.js
//  jquery.scrollTo.js
//  jquery.mwScrollTo.js
function Comments(containerElement, subject, fullSiteRoot, ajaxRoot)
{	
    this._commentsContainer = $("#" + containerElement); //this is the containing outer element for comments
    this._subject = subject;
    this._fullSiteRoot = fullSiteRoot;
    this._ajaxRoot = ajaxRoot;     

    this._replyToId = 0;

    this._state = {};
    this._commentId = "";

    // All posted comments will be first be put into this DIV and then moved to their correct location
    this._postedCommentsContainer = $("<div>");

    // See if we are linking directly to a comment
    var commentId = this.GetCommentIdFromWindow();
    if(commentId > 0)
    {
        //this will force an ajax call to load a page at the specific comment
        this.LoadCommentsPageFromCommentId(commentId);
    }
    else
    {
        this.RenderCommentsDefaultPage();
    }
}

Comments.prototype.LoadCommentsPageFromCommentId = function Comments_LoadCommentsPageFromCommentId(commentId)
{
    this._commentId = "";
    if(commentId)
    {
        this._commentId = commentId;
    }

    //combine the subject and commentId for the args
    var args = {};
    $.extend(args, this._subject, { commentEntryId: this._commentId });

    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + "/mw5/comments/widget.sync",
	    data: args,
		success: function(partialView)
		{
	        //render the full comments page (verify it's a <div> coming back)
			if(partialView && partialView.substr(0,4) == '<div')
			{
	            thisInstance._commentsContainer.html(partialView);
	        }
	    },
		complete: function(XMLHttpRequest, textStatus)
		{			
			if(textStatus == "success")
			{
	            //initialize object with json data from response header
	            //json values: commentCount, activePage, pageCount, visiblePages, direction
	            var jsonPagingData = thisInstance.GetJsonAsObject(XMLHttpRequest);

	            thisInstance.InitializePagination(
					jsonPagingData.commentCount,
					jsonPagingData.activePage,
					jsonPagingData.pageCount,
					jsonPagingData.visiblePages);
	        }
	    }
	});
}

Comments.prototype.RenderCommentsDefaultPage = function Comments_RenderCommentsDefaultPage()
{
    //check to see if comments are pre-loaded into the page by the view
    //if not - reload them via ajax
	if(this.AreCommentsRendered() === true)
	{
        //initialize pagination with values set by the view (widget.vm)
        this.InitializePagination(
			window._commentCount,
			window._commentActivePage,
			window._commentPageCount,
			window._commentVisiblePages);
    }
	else
	{
        //make an ajax call to render the default comments page - since the view hasn't already rendered it
        this.LoadCommentsPageFromCommentId("");
    }
}


Comments.prototype.AreCommentsRendered = function Comments_AreCommentsRendered()
{
    var commentsRendered = false;

    //check to see if these variables have been set by the view
    //if not - the view wasn't rendered properly
    if (window._commentCount &&
		window._commentActivePage &&
		window._commentPageCount &&
		window._commentVisiblePages)
	{
        commentsRendered = true;
    }

    return commentsRendered;
}

Comments.prototype.InitializePagination = function Comments_InitializePagination(commentCount, activePage, pageCount, visiblePages)
{
    //shove pagingData into state object	
    this._state = { commentCount: commentCount, activePage: activePage, pageCount: pageCount, visiblePages: visiblePages };

    this.SetPagination(this._state.activePage, pageCount > 1);

    // Move to the comment (if specified) - this function call may be overridden by another js object
    this.NavigateToComment();
}

Comments.prototype.GetCommentIdFromWindow = function Comments_GetCommentIdFromWindow()
{
    commentId = "";
    var results = window.location.href.match(/#comment(\d+)/);
    if (results && (results.length == 2))
    {
        commentId = results[1];
    }

    return commentId;
}

Comments.prototype.NavigateToComment = function Comments_NavigateToComment()
{
	if (this._commentId > 0)
    {    	
        $.mwScrollTo('#commententry' + this._commentId);
        this._commentId = "";
    }
}

Comments.prototype.Post = function Comments_Post() {
    var formattedCommentText = $('#commentBody')[0].value.replace(/\n/g, "<br />").trim(this.text);
    if (formattedCommentText.length == 0) {
        //if nothng added, redisplay (reset state of comments) and bail
        return;
    }

    $('#postcomment').hide();
    $('#cancelcomment').hide();
    document.body.style.cursor = 'wait';

    var trackReplies = $('#cbxtrackreply')[0].checked;

    var args = {};
    $.extend(args, { content: formattedCommentText, replyToId: this._replyToId, trackreplies: trackReplies }, this._subject);

    if (this._postedCommentsContainer) {
        var thisInstance = this;
        $.ajax(
		{
		    type: 'post',
		    url: this._ajaxRoot + "/mw5/comments/post.sync",
		    data: args,
		    success: function(partialView) {
		        //grab the posted comments html
		        thisInstance._postedCommentsContainer.html(partialView);
		    },
		    complete: function(XMLHttpRequest, textStatus) {
		        //display the comment
		        thisInstance.ShowPostedComments();
		    }
		});
    } 
	if (this._subject['s.typeName'] == 'story') 
	{
        // Omniture
        var s = s_gi('djglobal,djmarketwatch');
        s.prop45 = 'ugc_comment';
        void (s.tl(true, 'o', 'ugc_comment'));
    }
}

Comments.prototype.ShowPostedComments = function Comments_ShowPostedComments() {
    document.body.style.cursor = 'default';
    $('#communitycomments #commentpages').show(); //this will be hidden if zero comments on story
    $('#postcomment').show();
    $('#cancelcomment').show();

    // If posting a top level comment and not on the last page...move to that last page
    if ((this._replyToId == 0) && (this._state.activePage != this._state.pageCount)) {
        this.__ChangePage(this._state.pageCount);
    }

    //append the new comment into the container at correct location and show it
    $('#newcommentarea' + this._replyToId).append(this._postedCommentsContainer.html());
    $('#newcommentarea' + this._replyToId).parent().show();

    // If this if the first comment, we need to add a grouping class to the container
    // to ensure the comment borders display correctly--one subsequent adds, this will be there already	
    if (this._state.commentCount == 0) {
        $('#commentpages').addClass('group');
    }

    //Makes modification for group appropriate stylin
    $('#newcommentarea' + this._replyToId).parent().prev('.arrow').addClass('visible');

    //clear out the old text and checkbox
    $('#commentBody')[0].value = '';
    $('#cbxtrackreply')[0].checked = false;

    //open the main comment box
    this.OpenReplyBox($('#commentreplyarea'), 0, '', 'false');

    //update state
    this._state.commentCount = this._state.commentCount + 1;

    //configure other widgets
    if (this._state.commentCount == 1) {
        //call over to the commenter grid widget and show the first commenter
        if (MarketWatch.Community.CommenterGrid.UnhidePageOne != undefined) {
            MarketWatch.Community.CommenterGrid.UnhidePageOne();
        }

        //call over to the filter widget and unhide it
        if (MarketWatch.Community.FilteredCommentTabs.Unhide != undefined) {
            MarketWatch.Community.FilteredCommentTabs.Unhide();
        }
    }
}


Comments.prototype.HelpfulComment = function Comments_HelpfulComment(commentEntryId, wasHelpful) {
    // If this user has already "recommended/unrecommended" this comment, just bail
    if ($('.helpful' + commentEntryId).hasClass('helpful') ||
        $('.helpful' + commentEntryId).hasClass('unhelpful') ||
        $('.helpful' + commentEntryId).hasClass('your')) 
    {       
        return;
    }

    var args = { commentEntryId: commentEntryId, wasHelpful: wasHelpful };

    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + "/mw5/comments/helpfulcomment.sync",
	    data: args,
		complete: function(XMLHttpRequest, textStatus)
		{
	        //call complete by passing the full XHR
	        thisInstance.HelpfulComplete(XMLHttpRequest);
	    }
	});
    // Omniture
    if(wasHelpful)
    {
        var s=s_gi('djglobal,djmarketwatch');
        s.prop45='ugc_commenthelpful';
        void(s.tl(true, 'o', 'ugc_commenthelpful'));
    }
    else
    {
        var s=s_gi('djglobal,djmarketwatch');
        s.prop45='ugc__commentvoteDN';
        void(s.tl(true, 'o', 'ugc__commentvoteDN'));
    }   
}

Comments.prototype.HelpfulComplete = function Comments_HelpfulCompleteComplete(transport) {
    //get json from response header
    //json values: commentEntryId,wasHelpful,helpfulCount,unhelpfulCount
    var jsonHelpfulData = this.GetJsonAsObject(transport);

    //calculate totals
    var totalHelpfulCount = jsonHelpfulData.helpfulCount + jsonHelpfulData.unhelpfulCount;
    var netHelpfulCount = jsonHelpfulData.helpfulCount - jsonHelpfulData.unhelpfulCount;

    //mark the voting buttons as helpful/unhelpful
    if (Boolean(jsonHelpfulData.wasHelpful))
	{
        $('.helpful' + jsonHelpfulData.commentEntryId).addClass('helpful');
        $('.unhelpful' + jsonHelpfulData.commentEntryId).addClass('helpful');
    }
	else
	{
        $('.helpful' + jsonHelpfulData.commentEntryId).addClass('unhelpful');
        $('.unhelpful' + jsonHelpfulData.commentEntryId).addClass('unhelpful');
    }

    //update the text display with new vote counts	
    if (netHelpfulCount == 0)
        $('.numhelpful' + jsonHelpfulData.commentEntryId).html("Even (" + jsonHelpfulData.helpfulCount + " Up / " + jsonHelpfulData.unhelpfulCount + " Dn)");
    else if (netHelpfulCount > 0)
        $('.numhelpful' + jsonHelpfulData.commentEntryId).html("+" + netHelpfulCount + " Votes (" + jsonHelpfulData.helpfulCount + " Up / " + jsonHelpfulData.unhelpfulCount + " Dn)");
    else
        $('.numhelpful' + jsonHelpfulData.commentEntryId).html(netHelpfulCount + " Votes (" + jsonHelpfulData.helpfulCount + " Up / " + jsonHelpfulData.unhelpfulCount + " Dn)");
}

Comments.prototype.TrackReplies = function Comments_TrackReplies(commentEntryId)
{
    var args = { commentEntryId: commentEntryId };

    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + "/mw5/comments/trackreplies.sync",
	    data: args,
		success: function(partialView)
		{
	        //shove the partial view into the track element
	        $('#track' + commentEntryId).html(partialView);
	    }
	});
	
	var s = s_gi('djglobal,djmarketwatch');
	s.prop45 = 'ugc_commentTrack';
	void (s.tl(true, 'o', 'ugc_commentTrack'));        
	
}

Comments.prototype.TrackRepliesStop = function Comments_TrackRepliesStop(commentEntryId)
{              
    var args = { commentEntryId: commentEntryId };

    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + "/mw5/comments/trackrepliesstop.sync",
	    data: args,
		success: function(partialView)
		{
	        //shove the partial view into the track element
	        $('#track' + commentEntryId).html(partialView);
	    }
	});

	var s = s_gi('djglobal,djmarketwatch');
	s.prop45 = 'ugc_commentTrack';
	void (s.tl(true, 'o', 'ugc_commentTrackStop'));   	
	
}

Comments.prototype.EditComment = function Comments_EditComment(commentEntryId)
{
    var args = { commentEntryId: commentEntryId };

    var commentEntry = $('#commententry' + commentEntryId);
    var commentBody;

    if (commentEntry)
    {
        commentBody = commentEntry.find('.body');
    }

    if (commentBody.length == 1)
    {   
        //hide the edit comment link
        $('#editcomment' + commentEntryId).hide();

        $('#commentreplyarea').hide();  //hide main comment box
        $('[id^=_reply]').hide();  //hide every reply box (any element whose ID starts with '_reply')

        var thisInstance = this;
        $.ajax(
		{
		    type: 'post',
		    url: this._ajaxRoot + "/mw5/comments/editcomment.sync",
		    data: args,
			success: function(partialView)
			{
		        //shove the partial view into the comment body
		        commentBody.html(partialView);
		    }
		});
    }
}

Comments.prototype.PostEditComment = function Comments_PostEditComment(comment, commentEntryId)
{
    //comment is a jquery object
    var commentText = comment[0].value.replace(/\n/g, "<br />");

    var args = {};
    $.extend(args, { content: commentText }, this._subject, { commentEntryId: commentEntryId });

    var commentEntry = $('#commententry' + commentEntryId);
    var commentBody;

	if (commentEntry)
	{
        commentBody = commentEntry.find('.body');
    }

	if (commentBody.length == 1)
	{        
        var thisInstance = this;
        $.ajax(
		{
		    type: 'post',
		    url: this._ajaxRoot + "/mw5/comments/posteditcomment.sync",
		    data: args,
			success: function(partialView)
			{
		        //shove the partial view into the comment body
		        commentBody.html(partialView);

		        //re-show the edit comment link
		        $('#editcomment' + commentEntryId).show();

		        //re-show the main comment box
		        thisInstance.OpenReplyBox($('#commentreplyarea'), 0, '', 'false');
		    }
		});
    }
}

Comments.prototype.CancelEditComment = function Comments_CancelEditComment(commentEntryId)
{
    var args = { commentEntryId: commentEntryId };

    var commentEntry = $('#commententry' + commentEntryId);
    var commentBody;

	if (commentEntry)
	{
        commentBody = commentEntry.find('.body');
    }

    if (commentBody.length == 1)
	{    
        var thisInstance = this;
        $.ajax(
		{
		    type: 'post',
		    url: this._ajaxRoot + "/mw5/comments/canceleditcomment.sync",
		    data: args,
			success: function(partialView)
			{
		        //show the partial view into the comment body
		        commentBody.html(partialView);

		        //re-show the edit comment link
		        $('#editcomment' + commentEntryId).show();

		        //re-show the main comment box
		        thisInstance.OpenReplyBox($('#commentreplyarea'), 0, '', 'false');
		    }
		});
    }
}

Comments.prototype.__PreviousPage = function Comments_PreviousPage(elt)
{
    if (this._state.activePage > 1)
    {
        this.__ChangePage(this._state.activePage - 1, elt);
    }
}
Comments.prototype.__NextPage = function Comments_NextPage(elt)
{
    if (this._state.activePage < this._state.pageCount)
    {
        this.__ChangePage(this._state.activePage + 1, elt);
    }
}
Comments.prototype.__ChangePageId = function Comments_ChangePageId(pageId, elt)
{
    // Determine the next active page
    var pageNumber = this._state.pageLowerIndex + pageId - 1;

    this.__ChangePage(pageNumber, elt)
}

Comments.prototype.__ChangePage = function Comments_ChangePage(pageNumber, elt)
{    
    if (this._state.activePage == pageNumber)
        return;

    //Set page status to "waiting"
    this.SetWaitStatus();

    //determine if top or bottom pagination control was clicked
    var whichPaginationCtrl = 'unknown';
    while ((elt != null) && (whichPaginationCtrl == 'unknown'))
    {
        if (elt.id == 'toppagination')
            whichPaginationCtrl = 'top'
        else if (elt.id == 'bottompagination')
            whichPaginationCtrl = 'bottom'
        else
            elt = elt.parentNode;
    }

    // If this page has previously been shown, just "unhide" it
    if ($("#commentpage" + pageNumber).length > 0)
    {
        this.ChangePageToPreloadedPage(pageNumber, whichPaginationCtrl);
    }
    else
    {
        this.ChangePageToNonLoadedPage(pageNumber, whichPaginationCtrl);
    }

}

Comments.prototype.ChangePageToPreloadedPage = function Comments_ChangePageToPreloadedPage(pageNumber, whichPaginationCtrl)
{
    $("#commentpage" + pageNumber).show();
    $("#commentpage" + this._state.activePage).hide();
	if (whichPaginationCtrl == 'bottom')
	{
        //scroll to top pager controls
        $.mwScrollTo('#toppagination')

        //if on comments tab - scroll comment window to top comment on page
        $('#commentpages').mwScrollTo(0);
    }

    this.ChangePageComplete(pageNumber);
}

Comments.prototype.ChangePageToNonLoadedPage = function Comments_ChangePageToNonLoadedPage(pageNumber, whichPaginationCtrl)
{
    //retrieve the page from the server
    var args = {};
    $.extend(args, { pageNumber: pageNumber }, this._subject);

    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + "/mw5/comments/getpage.sync",
	    data: args,
		success: function(partialView)
		{
	        $('#commentpages').append(partialView);

	        $("#commentpage" + thisInstance._state.activePage).hide();
			if (whichPaginationCtrl == 'bottom')
			{
	            //scroll to top pager controls
	            $.mwScrollTo('#toppagination')
	        }

	        //if on comments tab - scroll comment window to top comment on page
	        $('#commentpages').mwScrollTo(0);
	    },
		complete: function(XMLHttpRequest, textStatus)
		{
	        thisInstance.ChangePageComplete(pageNumber);
	    }
	});
}

Comments.prototype.ChangePageComplete = function Comments_ChangePageComplete(pageNumber)
{
    this.SetPagination(pageNumber, true);
    this._state.activePage = pageNumber;

    //Set page status to "ready"
    this.SetReadyStatus();
}

Comments.prototype.SetPagination = function Comments_SetPagination(pageNumber, hasMultiplePages)
{	
    this._state.pageLowerIndex = 1;
    var topPageLinks = $('#toppagination a.commentpagelink');
    var bottomPageLinks = $('#bottompagination a.commentpagelink');

    this.SetPaginationPrevNext(pageNumber);


    if (this._state.visiblePages < this._state.pageCount)
    {
        //set up pagination where there are more pages than are visible
        this._state.pageLowerIndex = pageNumber - Math.floor(this._state.visiblePages / 2);
        if (this._state.pageLowerIndex < 1)
            this._state.pageLowerIndex = 1;
        else if ((this._state.pageLowerIndex + this._state.visiblePages - 1) > this._state.pageCount)
            this._state.pageLowerIndex = this._state.pageCount - this._state.visiblePages + 1;

        //set current page to selected
        topPageLinks.removeClass('selected');
        bottomPageLinks.removeClass('selected');

        for (var i = 1; i <= this._state.visiblePages; i++)
        {
            var pageNum = this._state.pageLowerIndex + i - 1;
            $(topPageLinks[i - 1]).html(pageNum.toString());
            $(bottomPageLinks[i - 1]).html(pageNum.toString());

            if (pageNum == pageNumber)
            {
                $(topPageLinks[i - 1]).addClass('selected');
                $(bottomPageLinks[i - 1]).addClass('selected');
            }
        }
    }
    else
    {
        //set up pagination where all page links are visible
        topPageLinks.removeClass('selected');
        bottomPageLinks.removeClass('selected');
        if (topPageLinks.length >= pageNumber)
            $(topPageLinks[pageNumber - 1]).addClass('selected');
        if (bottomPageLinks.length >= pageNumber)
            $(bottomPageLinks[pageNumber - 1]).addClass('selected');
    }

    //show the pagination controls now that they've been set
    if(hasMultiplePages === true)
    {
        this.ShowPaginationControls();
    }
}

Comments.prototype.SetPaginationPrevNext = function Comments_SetPaginationPrevNext(pageNumber)
{
    //enable/disable controls if on first page
    var paginations = $('#toppagination, #bottompagination');
	if (pageNumber == 1)
	{
        //show disabled previous link
        $('span.prev.enabled', paginations).hide();
        $('span.prev.disabled', paginations).show();
    }
	else
	{
        //show enabled previous link
        $('span.prev.enabled', paginations).show();
        $('span.prev.disabled', paginations).hide();
    }
    //enable/disable controls related to last page
	if (pageNumber == this._state.pageCount)
	{
        //show disabled next link
        $('span.next.enabled', paginations).hide();
        $('span.next.disabled', paginations).show();
    }
	else
	{
        //show enabled next link
        $('span.next.enabled', paginations).show();
        $('span.next.disabled', paginations).hide();
    }
}

Comments.prototype.OpenReplyBox = function Comments_OpenReplyBox(targetElement, commentEntryId, replyToName, moveToCommentBox) {
    this._replyToId = commentEntryId;

    $('#commentreplyarea').hide();  //hide main comment box
    $('[id^=_reply]').hide();  //hide every reply box (any element whose ID starts with '_reply')

    //put the comment box inside the current reply location
    $(targetElement).append($('#newcomment'));

    //clear the text box
    if ($('#commentBody').length == 1) {
        $('#commentBody')[0].value = '';
    }

    //show the box
    $(targetElement).show();

    //set comment box title
    if (replyToName) {
        $('#newcommenttitle').html("Reply to " + replyToName + "'s comment");
        //set cursor focus (on for replies to avoid jump if the user cancels)
        $('#commentBody').focus();
    }
    else
        $('#newcommenttitle').html("Add a Comment");
}

Comments.prototype.__SendMessageAction = function Comments_SendMessageAction(from, to)
{
    window.open(this._fullSiteRoot + '/' + from + '/mailbox/compose?to=' + to);
}

Comments.prototype.__SendFriendRequestAction = function Comments_SendFriendRequestAction(commentEntryId, from, to)
{
    var thisInstance = this;
    $.ajax(
	{
	    type: 'post',
	    url: this._ajaxRoot + '/mw5/comments/invitefriendsilently.sync?name=' + to,
	    data: {},
	    complete: function(XMLHttpRequest, textStatus)
	    {
	        //get json from response header
	        //json values: commentEntryId,wasHelpful,helpfulCount,unhelpfulCount									
			if(textStatus == "success")
			{
	            var inviteSentData = thisInstance.GetJsonAsObject(XMLHttpRequest);
				if (inviteSentData.inviteSent) 
				{
	                $('#sendrqst' + commentEntryId).hide();
	                $('#sentrqst' + commentEntryId).show();

	                //briefly display "message sent"
	                var rqstSentMsgId = '#rqstsentmsg' + commentEntryId;
	                $(rqstSentMsgId).fadeIn(500);
	            }
	        }
	    }
	});
}

Comments.prototype.ReportAbuse = function Comments_ReportAbuse(commentId)
{
	if(commentId > 0)
	{
        var thisInstance = this;
        $.ajax(
		{
		    type: 'post',
		    url: this._ajaxRoot + "/mw5/comments/report.sync",
		    data: { commentId: commentId },
			success: function(partialView)
			{
		        //shove the partial view into the link element
		        $('#reportcomment' + commentId).html(partialView);
		    }
		});
    }
}

Comments.prototype.GetJsonAsObject = function Comments_GetJsonAsObject(XMLHttpRequest)
{
    var jsonObject;

    var jsonString = XMLHttpRequest.getResponseHeader("X-JSON");
	if(jsonString != null)
	{		   
        jsonObject = $.evalJSON(jsonString);
    }

    return jsonObject;
}

Comments.prototype.SetWaitStatus = function Comments_SetWaitStatus()
{
    $("body").css("cursor", "progress");
}

Comments.prototype.SetReadyStatus = function Comments_SetReadyStatus()
{
    $("body").css("cursor", "auto");
}

Comments.prototype.ShowPaginationControls = function Comments_ShowPaginationControls()
{
    //show both top and bottom pagination controls
    $('#toppagination, #bottompagination').css('visibility','visible');
    $('#toppagination, #bottompagination').show();
}

Comments.prototype.SetTextAreaFocus = function Comments_SetTextAreaFocus()
{
    //hide the ghost text
    $('.commentghosttext').hide();
    $('#commentBody').focus();
}

Comments.prototype.SetTextAreaBlur = function Comments_SetTextAreaBlur()
{
    //show the ghost text if the comment box is empty
	if($('#commentBody')[0].value.length == 0)
	{
        $('.commentghosttext').show();
    }
}

Comments.prototype.DisplayLoginScreen = function Comments_DisplayLoginScreen()
{
	if(MarketWatch.Member.isCommunityMember !== true)
	{
        MarketWatch.Member.startCmtyJitLogin();
    }
}
