/**
 * @filename brain.js
 *
 * Javascript main file for the eComments Web App
 *
 * @author Cristin Iosif <cristin.iosif@gmail.com>
 */

/**
 * Application's settings
 */
 // @var commentsPerPage - the number of comments per page; set this to 0 if you don't want pagination
 var commentsPerPage = 2;
 // @var orderCommentsAfterDateASC - set this to true if you want the comments displayed in ascending order
 //                                  after date; if set to false the comments will be displayed in descending order
 var orderCommentsAfterDateASC = false;
 // @var int reloadCommentsButton - set this to an integer value representing the interval when the user can reload comments
 //                                 if this is set to 0, then the button will not be displayed
 var reloadCommentsButton = 15;
 // @var bool replyToTeply - set this to true if you want the ability to reply to a reply; set it to false, and the
 //                          reply link will only show on the original comment
 var replyToReply = true;

/**
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * DO NOT EDIT BELOW THIS LINE!
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */

/**
 *  eComments - the main JS Object used by the eComments App
 */
var eComments = {
    // @var string pageId - the unique identifier of the page where the commenting system is implemented
    pageId: "",
    // @var string containerId - the ID of the container where the commenting system will be inserted
    containerId: "",
    // @var int commentsPerPage - the number of comments per page; is set in the Application's settings area
    commentsPerPage: commentsPerPage,
    // @var bool orderCommentsAfterDateASC - sets the order in which the comments are displayed; is set in the Application's settings area
    orderCommentsAfterDateASC: orderCommentsAfterDateASC,
    // @var int reloadCommentsButton - set this to an integer value representing the interval when the user can reload comments                                   add comment form; if set to false the button will be hidden
    reloadCommentsButton: reloadCommentsButton,
    // @var JSON Object - contains the comments retrieved from the server
    comments: "",
    // @var int pages - the number of pages
    pages: "",
    // @var int nrOfComments - the number of comments
    nrOfComments: "",
    // @var int currentPage - the current page displayed
    currentPage: 0,
    // @var jQuey object ulPagesObj - the div's object where the pagination will be inserted
    paginationUL: "",
    // @var jQuery Object formStatusObj - the container used for displaying the status of a ajax request
    formStatusObj: "",
    // @var string pathToApp - the path from the page on which the commenting system is implemented to the eComments App Directory
    pathToApp: "",
    /**
     * The 'init' function is the function called when the commenting system is loading. This function checks to see if there is a database table create,
     * if not it creates one. After that, it creates the HTML structure of the commenting system and calls the getComments function.
     * @param array params - can contain the pageId, containerId, pathToApp, orderCommentsAfterDateASC or commentsPerPage parameters
     * @return void
     */
    init: function(params){
        var error = 0;
        var errorMsg = "";
        if(params != undefined){
            if(params["pageId"] != undefined) this.pageId = params["pageId"];
            else {
                error = 1;
                errorMsg = "Error #"+ error +": The 'pageID' is not defined!\n";
            }
            if(params["containerId"] != undefined) this.containerId = params["containerId"];
            else {
                error = 2;
                errorMsg += "Error #"+ error +": The 'containerId' is not defined!";
            }
            if(params["pathToApp"] != undefined) this.pathToApp = params["pathToApp"];
            if(params["orderCommentsAfterDateASC"] != undefined && typeof(params["orderCommentsAfterDateASC"]) == "boolean"){
                this.orderCommentsAfterDateASC = params["orderCommentsAfterDateASC"];
            }
            if(params["commentsPerPage"] != undefined) this.commentsPerPage = params["commentsPerPage"];
            if(params["reloadCommentsButton"] != undefined) this.reloadCommentsButton = params["reloadCommentsButton"];
        }else{
            error = 3;
            errorMsg = "The 'pageId' and 'containerId' are not defined!";
        }

        if(error == 0){
            $.ajax({
                type: "GET",
                url: eComments.pathToApp+"php/brain.php",
                data: "action=init",
                dataType: "json",
                success: function(data){
                    if(data["status"] != 0){
                        eComments.displayError("Error #"+data["status"]+": "+data["error"]);
                    }else eComments.getComments();
                }
            });
            htmlStruct = '<div id="eCommentsContainer">';
            htmlStruct += '<div id="eCommentsHeader">';
            htmlStruct += '<span class="title">Commenti</span><a href="#eCommentsForm-title" class="go-to-add-form">Lascia un commento</a>';
            if(eComments.reloadCommentsButton != undefined && eComments.reloadCommentsButton > 0){
                htmlStruct += '<a href="#" id="reload-comments-button" class="reload-comments-button" onclick="eComments.reloadComments();">Aggiorna i commenti</a>';
            }
            htmlStruct += '</div>';
            htmlStruct += '<div id="eComments"></div>';
            htmlStruct += '<div id="loading-container">Loading...</div>';
            if(eComments.commentsPerPage != 0) {
                htmlStruct += '<div id="eCommentsPagination"><ul id="eCommentsPaginationUL"></ul></div>';
            }
            htmlStruct += '<div id="eCommentsForm"></div>';
            htmlStruct += '</div>';
            $(this.containerId).html(htmlStruct);
            this.showForm();

            eComments.formStatusObj = $("#form-status");
            eComments.paginationUL = $("#eCommentsPaginationUL");
        }else {
            alert("eComments\n"+errorMsg)
        }

    },
    /**
     * The 'getComments' function retrieves the comments from the database and displayes them by calling the 'displayCommentsPerPage' function
     * @return void
     */
    getComments: function(){
        var eCommentsObj = $("#eComments");
        eCommentsObj.fadeOut("fast", function (){
            $("#loading-container").fadeIn("fast");
        $.ajax({
           type: "GET",
           url: eComments.pathToApp+"php/brain.php",
           data: "action=get_comments&page_id="+encodeURIComponent(eComments.pageId)+"&orderAfterDateASC="+eComments.orderCommentsAfterDateASC+"&data="+ new Date().getTime(),
           dataType: "json",
           success: function(data){
               var status = parseInt(data["status"]);
               if(status == 0){
                    eComments.comments = data["comments"];
                    eComments.nrOfComments = data["nrOfComments"];
                    
                    if(eComments.commentsPerPage != 0){
                        eComments.pages = Math.ceil(eComments.nrOfComments/eComments.commentsPerPage);
                        var pages = '<li onclick="javascript:eComments.displayPrevPage();">Prec.</li>';
                        for(var i=0;i<eComments.pages;i++){
                            pages += '<li id="ecomments-pagination-'+(i+1)+'" onclick="javascript:eComments.displayCommentsPage('+ (i+1) + ');">'+ (i+1) +'</li>';
                        }
                        pages += '<li onclick="javascript:eComments.displayNextPage();">Succ.</li>';
                        eComments.paginationUL.html(pages);
                    }
                    eComments.displayCommentsPage(1);
               }else{
                   // if status is -2, then there aren't any comments to display
                   if(status == -2){
                        eComments.displayMsg(data["error"]);
                   }else {
                        eComments.displayError("Error #"+data["status"]+": "+data["error"]);
                   }
                   var eCommentsObj = $("#eComments");
                   $("#loading-container").fadeOut("fast", function(){
                       eCommentsObj.fadeIn("slow")
                   });
               }
           }
        });
        });
    },
    /**
     * The 'displayCommentsPerPage' function displays a page with comments, or all the comments if the pagination is disabled
     * @param int pageNr - the number of the page that needs to be displayed
     * @return void
     */
    displayCommentsPage: function(pageNr){
        if(eComments.currentPage != pageNr){
            var eCommentsObj = $("#eComments");
            eCommentsObj.fadeOut("fast", function (){
            
            if(eComments.commentsPerPage != 0){
                $("#ecomments-pagination-"+(eComments.currentPage)).removeClass("current-page");
                eComments.currentPage = pageNr;
                eComments.updatePagination();
                $("#ecomments-pagination-"+(eComments.currentPage)).addClass("current-page");

                var itemStart = (pageNr-1)*eComments.commentsPerPage;
                var itemEnd = pageNr*eComments.commentsPerPage;
                if(itemEnd > eComments.nrOfComments) itemEnd = eComments.nrOfComments;
            }else {
                var itemStart = 0;
                var itemEnd = eComments.nrOfComments;
            }
            var commentsHTML = "";
            var commId, author, comment, date, nrOfReplyComments;
            for(var i=itemStart;i<itemEnd;i++){
                commId = eComments.comments[i]["id"];
                author = eComments.comments[i]["author"];
                comment = eComments.comments[i]["comment"];
                date = eComments.comments[i]["date"];
                commentsHTML += '<div class="eCommentsBox" id="eComment'+commId+'">';
                    commentsHTML += '<div class="info">';
                        commentsHTML += '<a href="#eCommentsForm" onclick="eComments.reply('+commId+',\''+author+'\')" class="reply">Rispondi</a>';
                        commentsHTML += '<span class="commNr">#'+(i+1)+'</span>';
                        commentsHTML += '<span class="author">'+author+'</span>';
                        commentsHTML += '<span class="spacer">said on </span>';
                        commentsHTML += '<span class="date">'+date+"</span>";
                    commentsHTML += '</div>';
                    commentsHTML += '<div class="arrow"></div>';
                    commentsHTML += '<div class="commentCont">';
                        commentsHTML += '<div class="comment">'+comment+'</div>';
                    commentsHTML += '</div>';
                    // REPLIED COMMENTS
                    // check for replied comments
                    nrOfReplyComments = eComments.comments[i]["nrOfReplyComments"];
                    if(nrOfReplyComments > 0){
                        commentsHTML += '<div class="eCommentsReplies">';
                        replyComments = eComments.comments[i]["replyComments"];
                        // display the replied comments
                        for(var j=0;j<nrOfReplyComments;j++){
                            author = replyComments[j]["author"];
                            comment = replyComments[j]["comment"];
                            date = replyComments[j]["date"];
                            commentsHTML += '<div class="reply">';
                                commentsHTML += '<div class="reply-pointer"></div>';
                                commentsHTML += '<div class="eCommentsReplyBox">';
                                    commentsHTML += '<div class="info">';
                                         if(replyToReply == true)
                                            commentsHTML += '<a href="#eCommentsForm" onclick="eComments.reply('+commId+',\''+author+'\')" class="reply">Rispondi</a>';
                                         commentsHTML += '<span class="author">'+author+'</span>';
                                         commentsHTML += '<span class="spacer">ha risposto il </span>';
                                         commentsHTML += '<span class="date">'+date+"</span>";
                                     commentsHTML += '</div>';
                                     commentsHTML += '<div class="arrow"></div>';
                                     commentsHTML += '<div class="commentCont">';
                                         commentsHTML += '<div class="comment">'+comment+'</div>';
                                     commentsHTML += '</div>';
                                commentsHTML += '</div>';
                            commentsHTML += '</div>';
                        }
                        commentsHTML += '</div>';
                    }
                commentsHTML += '</div>';
            }
            $(this).html(commentsHTML);
            $("#loading-container").fadeOut("fast", function(){
                eCommentsObj.fadeIn("slow");
            });

            });
        }
    },
    /**
    * The displayNextPage function displays the next page of comments. Is the onClick event for the next button from the pagination.
     * @return void
     */
    displayNextPage: function(){
        if(eComments.currentPage + 1 > eComments.pages){
            eComments.displayCommentsPage(1);
	}else {
            eComments.displayCommentsPage(eComments.currentPage + 1);
	}
    },
    /**
     * The displayPrevPage function displays the previous page of comments. Is the onClick event ofr the prev button from the pagination.
     * @return void
     */
    displayPrevPage: function(){
	if(eComments.currentPage - 1 <= 0){
        	eComments.displayCommentsPage(eComments.pages);
	}else {
            eComments.displayCommentsPage(eComments.currentPage - 1);
        }
    },
    /**
     * The updatePagination function updates the pagination according to the current page.
     * @return void
     */
    updatePagination: function(){
        var nrOfPags = 7;
        var pages = '<li onclick="javascript:eComments.displayPrevPage();">Prec.</li>';
        if(eComments.currentPage - 3 <= 0){
            for(var i=0;i<((eComments.pages < 7)?eComments.pages:7);i++){
                pages += '<li id="ecomments-pagination-'+(i+1)+'" onclick="javascript:eComments.displayCommentsPage('+ (i+1) + ');">'+ (i+1) +'</li>';
            }
        }else{
            if(eComments.currentPage + 3 >= eComments.pages){
                // how we calculate the start page
                // if there aren't enough pages after the current page we take from the front of the current page
                // how much are missing after the current page
                // for example if you have only 2 pages after current page and we need 3, then take 4 from the front of current page
                var startPag = eComments.currentPage - 3 - 1 - (eComments.currentPage + 3 - eComments.pages);
                if(startPag < 0) startPag = 0;
                for(var i=startPag;i<eComments.pages;i++){
                    pages += '<li id="ecomments-pagination-'+(i+1)+'" onclick="javascript:eComments.displayCommentsPage('+ (i+1) + ');">'+ (i+1) +'</li>';
                }
            }else{
                for(var i=(eComments.currentPage - 3-1);i<((eComments.currentPage + 3 < eComments.pages)?eComments.currentPage+3:eComments.pages);i++){
                    pages += '<li id="ecomments-pagination-'+(i+1)+'" onclick="javascript:eComments.displayCommentsPage('+ (i+1) + ');">'+ (i+1) +'</li>';
                }
            }
        }
        pages += '<li onclick="javascript:eComments.displayNextPage();">Succ.</li>';
        eComments.paginationUL.html(pages);
    },
    /**
     * The 'reloadComments' function reload the comments from the server.
     * @return void
     */
    reloadComments: function(){
        eComments.currentPage = -1;
        $("#reload-comments-button").fadeOut("fast");
        eComments.getComments();
        setTimeout("eComments.showReloadCommentsButton()", eComments.reloadCommentsButton * 1000);
    },
    showReloadCommentsButton: function(){
        $("#reload-comments-button").fadeIn("slow");
    },
    /**
     * The 'showForm' function displays the form used by users to post comments.
     * @return void
     */
    showForm: function(){
        var form = "";
            form += '<div id="eCommentsForm-title"><span>Lascia il tuo commento</span> \n\
                    <span class="reply-to" id="reply-to"><span id="reply-to-author">Rispondi a</span> <span onclick="eComments.hideReplyTo()" id="reply-to-cross"></span></span></div>';
            form += '<form onsubmit="eComments.addComment(); return false;">';
                form += '<input type="hidden" id="reply-to-id" />'
                form += '<label>Name <small>(required)</small></label>';
                form += '<input type="text" id="author" placeholder="Il tuo Nome" />';
                form += '<label>Email <small>(obbligatorio, ma non lo rendiamo pubblico)</small></label>';
                form += '<input type="text" id="email" placeholder="La tua Email" />';
                form += '<label>Commento <small>(obbligatorio)</small></label>';
                form += '<textarea id="comment" style="width: 95%; height: 100px;" placeholder="Il tuo commento"></textarea>';
                form += '<label>Antispam <small>(obbligatorio)</small></label>';
                form += '<input type="text" id="captcha_code" />';
                form += '<span id="captcha_container"><img src="'+eComments.pathToApp+'css/img/2.gif" id="captcha_image" /><img src="'+eComments.pathToApp+'css/img/refresh.png" onclick="eComments.requestCaptchaImage()" id="reload-captcha" title="Get a new verification code." /></span>';
                form += '<div style="clear: both"></div>';
                form += '<input type="submit" class="submit" value="Invia Commento" />';
                form += '<span id="form-status"></span><div style="clear: both"> </div>';
            form += '</form>';
       $(this.containerId).find("#eCommentsForm").html(form);

       // request a captcha image
       this.requestCaptchaImage();
    },
    /**
     * The 'addComment' function is used to add a comment to the database.
     * @return void
     */
    addComment: function(){
        var author = $("#author").attr("value");
        var email = $("#email").attr("value");
        var comment = $("#comment").attr("value");
        var replyToId = parseInt($("#reply-to-id").attr("value"));
        var captchaCode = $("#captcha_code").attr("value");
        var error = 0;
        // here goes the validation
        // Username and password patterns used fo validation
	// Supports alphabets and numbers
	// - no special characters except '_'
	// - min 3 and max 20 chars
	var author_patt = /^[A-Za-z0-9_]{3,20}$/;
	// Email supports special characters
	// - min length 10 max 30 chars
	var email_patt = /^[A-Za-z0-9-\._]+@[A-Za-z0-9-]+\.[A-Za-z]{2,4}(\.[A-Za-z]{2}){0,1}$/;

	if(!author_patt.test(author)){
            $("#author").addClass("error");
            error = 1;
	}else {
            $("#author").removeClass("error");
	}
	if(!email_patt.test(email)){
            $("#email").addClass("error");
            error = 2;
	}else {
            $("#email").removeClass("error");
	}
        if(comment.length <= 0){
            $("#comment").addClass("error");
            error = 3;
        }else $("#comment").removeClass("error");
        if(replyToId < 0){
            replyToId = -1;
        }
        if(captchaCode.length <= 0){
            $("#captcha_code").addClass("error");
            error = 4;
        }
        if(error == 0){
            eComments.formStatusObj.removeClass();
            eComments.formStatusObj.addClass("form-status-loading");
            eComments.formStatusObj.html("Loading...");

            var pageId = encodeURIComponent(eComments.pageId);
            author = encodeURIComponent(author);
            email = encodeURIComponent(email);
            comment = encodeURIComponent(comment);
            replyToId = encodeURIComponent(replyToId);
            captchaCode = encodeURIComponent(captchaCode);
            
            $.ajax({
                type: "POST",
                url: eComments.pathToApp+"php/brain.php",
                data: "action=add_comment&page_id="+pageId+"&author="+author+"&email="+email+"&comment="+comment+"&reply_to_id="+replyToId+"&captcha_code="+captchaCode,
                dataType: "json",
                success: function(data){
                    eComments.formStatusObj.removeClass("form-status-loading");
                    if(data["status"] == 0){
                        // Set the currentPage to -1 so that when the getComments function is called, this will display the added comment
                        // because displayComments will not display the comments if the currentPage is equal to the first page
                        eComments.currentPage = -1;
                        eComments.clearCommentForm();
                        eComments.formStatusObj.removeClass();
                        eComments.formStatusObj.addClass("form-status-ok");
                        eComments.formStatusObj.html(data["msg"]);
                        eComments.getComments();
                        // reload captcha image
                        eComments.requestCaptchaImage();
                    }else {
                        switch(data["status"]){
                            case 1:{
                                    $("#author").addClass("error");
                            }break;
                            case 2:{
                                    $("#email").addClass("error");
                            }break;
                            case 3:{
                                    $("#comment").addClass("error");
                            }break;
                            case 31:{
                                    $("#captcha_code").addClass("error");
                            }break;
                        }
                        eComments.formStatusObj.removeClass();
                        if(data["status"] == 5){
                            eComments.formStatusObj.addClass("form-status-msg");
                            eComments.clearCommentForm();
                        }else eComments.formStatusObj.addClass("form-status-error");
                        eComments.formStatusObj.html(data["msg"]);
                    }
                    eComments.hideReplyTo();
                }
            });
        }

    },
    /**
     * The 'reply' function is used to reply to a comment. It adds the id of the comment in the #reply-to-id hidden field.
     * It also displayes a message in the add comment form informing the user about the comment they are replying to.
     * @return void
     */
    reply: function(id, author){
        $("#reply-to-author").html("Reply to "+author);
        $("#reply-to-id").val(id);
        $("#reply-to").fadeIn();
    },
    /**
     * The 'hideReplyTo' function is used to hide the #reply-to container and to clear the valueof the hidden field #reply-to-id.
     * @return void
     */
    hideReplyTo: function(){
        $("#reply-to").fadeOut();
        $("#reply-to-id").val("");
    },

    /**
     * The 'clearCommentForm' function is used the clear the fields of the form.
     * @return void
     */
    clearCommentForm: function(){
        $("#eCommentsForm :text").attr("value", "");
        $("#eCommentsForm textarea").val("");
        $("#captcha_code").removeClass("error");
    },
    /**
     * The 'displayError' function is used to display an error.
     * @return void
     */
    displayError: function(errorMsg){
        var eCommentsContObj = $("#eComments");
        eCommentsContObj.html(errorMsg);
        eCommentsContObj.addClass("eComments-error");
    },
    /**
     * The 'displayMsg' function is used to display a message.
     * @return void
     */
    displayMsg: function(msg){
        var eCommentsContObj = $("#eComments");
        eCommentsContObj.html(msg);
        eCommentsContObj.addClass("eComments-msg");
    },
    /**
     * The 'requestCaptchaImage' function makes a call to php/brain.php for a new captcha image.
     */
    requestCaptchaImage: function(){
        var captcha_image = $("#captcha_container img:first-child");
        captcha_image.fadeOut("fast", function(){
            var d = new Date();
            captcha_image.attr("src",eComments.pathToApp+'php/brain.php?action=get_captcha&time='+d.getTime());
            captcha_image.fadeIn("fast");
        });
    }
}

