
var Comments =
{
    commentTemplate: null,
    commentRequests: {},
    editingPostId: null,
    submittingPostId: null,

    init: function()
    {
        this.commentTemplate = new Template("commentTemplate");

        if (window.location.hash == "#comments")
        {
            var firstBlogPost = getElementByClass(document.documentElement, "blogPost");
            var postId = firstBlogPost.id.substr(4);
            this.toggle(postId);
        }
    },

    onURLChange: function()
    {
    },

    onClick: function(postId, event)
    {
        preventDefault(event);
    
        Comments.toggle(postId);
    },

    ////////////////////////////////////////////////////////////////////////////////////////////////

    toggle: function(postId)
    {
        var postElt = $("post" + postId);
        var commentLinkBox = getElementByClass(postElt, "commentLinkBox");
    
        if (hasClass(commentLinkBox, "toggled"))
            this.show(postId, true);
        else
            this.show(postId);
    },
    
    show: function(postId, hide)
    {
        var postElt = $("post" + postId);
        var commentLinkBox = getElementByClass(postElt, "commentLinkBox");
    
        if (hide)
        {
            removeClass(commentLinkBox, "toggled");
            removeClass(commentLinkBox, "ready");
            this.showEditor(postId, true);
            $("post" + postId + "Comments").style.display = "none";
        }
        else
        {
            addClass(commentLinkBox, "toggled");
            this.load(postId);
        }
    },
    
    showEditor: function(postId, hide)
    {
        if (!hide && this.editingPostId)
            this.showEditor(this.editingPostId, true);
    
        if (!postId)
            postId = this.editingPostId;
        
        if (!postId)
            return;
            
        var postElt = $("post" + postId);
        var commentLinkBox = getElementByClass(postElt, "commentLinkBox");
        if (!hide && hasClass(commentLinkBox, "editing"))
            return;
    
        var commentEditorBox = $("commentEditorBox");
        
        if (hide)
        {
            commentEditorBox.style.display = "none";
            removeClass(commentLinkBox, "editing");
            this.editingPostId = null;
        }
        else
        {
            this.editingPostId = postId;
            $("commentEntryId").value = Number(postId);
            
            addClass(commentLinkBox, "editing");
    
            commentEditorBox.style.display = "block";
            $("commentEditor").value = "";
    
            var commentsElt = $(postElt.id + "Comments");
            commentsElt.parentNode.insertBefore(commentEditorBox, commentsElt);
            
            var emptyName = LabeledInput.apply($("commentName"), "Your Name");
            var emptyEmail = LabeledInput.apply($("commentEmail"), "Your E-mail or URL");
            $("commentEditor").focus();
            
            smoothScrollIntoView(commentEditorBox);
        }
    },
    
    ////////////////////////////////////////////////////////////////////////////////////////////////

    load: function(postId)
    {
        var postElt = $("post" + postId);
        var commentLinkBox = getElementByClass(postElt, "commentLinkBox");
        addClass(commentLinkBox, "loading");
        
        var url = "/blog/comments/" + postId + ".xml";
    
        // Add the current time to the url to make it unique so that we skip the cache 
        var args = new Date().getTime();
        
        var req = loadXMLDocument(url, args, function(doc) { Comments.onLoad(doc, postId); });
        this.commentRequests[postId] = req;
    },
    
    cancelLoad: function(postId)
    {
        if (postId in this.commentRequests)
        {
            this.commentRequests[postId].abort();
            delete this.commentRequests[postId];
        }
    
        Comments.show(postId, true);
    },
    
    onLoad: function(doc, postId)
    {
        delete this.commentRequests[postId];
    
        var postElt = $("post" + postId);
    
        var commentLinkBox = getElementByClass(postElt, "commentLinkBox");
        removeClass(commentLinkBox, "loading");
        addClass(commentLinkBox, "ready");
    
        var commentsBox = $("post" + postId + "Comments");
        clearChildren(commentsBox);
            
        // Create and insert the comment elements
        var commentCount = 0;
        var items = doc.documentElement.childNodes;       
        for (var i = 0; i < items.length; ++i)
        {
            if (items[i].nodeType == 1)
            {
                ++commentCount;
                var id = items[i].getAttribute("id");
                var author = Comments.readXMLNodeValue(items[i], "author");
                var email = Comments.readXMLNodeValue(items[i], "email");
                var url = Comments.readXMLNodeValue(items[i], "url");
                var timestamp = Comments.readXMLNodeValue(items[i], "timestamp");
                var body = Comments.readXMLNodeValue(items[i], "text");
                
                Comments.insertCommentBox(commentsBox, id, author, email, url, timestamp, body);
            }
        }
    
        commentsBox.style.display = "block";

        if (commentCount == 0)
            this.showEditor(postId);
        else
            smoothScrollIntoView(commentsBox);
    },
    
    insertCommentBox: function(commentsBox, id, author, email, url, timestamp, body)
    {
        var commentElt = this.commentTemplate.createTemplate();
        commentElt.id = id;
        
        if (email)
            url = "mailto:" + email;
        
        // If no url/email is provided then don't put a link around the author name
        if (url)
        {
            var html = '<a href="' + url + '">' + author + '</a>';
            this.commentTemplate.setHTMLValue(commentElt, "author", html);
        }
        else
            this.commentTemplate.setTextValue(commentElt, "author", author);
    
        // Format the date to look pretty (no offense to all you ISO members out there)
        var theDate = new Date(timestamp);
        var dateFormatted = 
            (theDate.getHours() > 11 ? theDate.getHours()-11 : theDate.getHours())
            + (theDate.getHours() > 11 ? "pm" : "am");
        this.commentTemplate.setTextValue(commentElt, "timestamp", dateFormatted);
        
        this.commentTemplate.setHTMLValue(commentElt, "content", body);
    
        commentsBox.insertBefore(commentElt, commentsBox.firstChild);
        
        if (commentsBox.childNodes.length % 2)
            setClass(commentElt, "commentBoxOdd");
    
        return commentElt;
    },
        
    ////////////////////////////////////////////////////////////////////////////////////////////////

    onSubmit: function(event)
    {
        var commentName = $("commentName");
        var commentEditor = $("commentEditor");
        var commentEmail = $("commentEmail");    
    
        if (!commentName.value || commentName.value == commentName.defaultValue)
        {
            alert("You need a name to comment on my website.  Feel free to make one up.");
            commentName.focus();
            event.preventDefault();
        }
        else if (!commentEditor.value)
        {
            alert("Are you going to write something or not?");
            commentEditor.focus();
            event.preventDefault();
        }
        else
        {
            this.submittingPostId = $("commentEntryId").value;
    
            var body = Comments.textToHTML(commentEditor.value);
    
            var commentsBox = $("post" + this.editingPostId + "Comments");
            var commentBox = Comments.insertCommentBox(commentsBox, "", $("commentName").value,
                $("commentEmail").value, null, new Date(), body);
        
            this.showEditor(this.editingPostId, true);
        
            var commentProgress = $("commentEditorProgress");
            commentProgress.style.display = "block";
            commentBox.appendChild(commentProgress);
        
            var emailRegex = /(.*?)\@(.*?)\.(.*)/i;
            if (emailRegex.test(commentEmail.value))
                commentEmail.name = "email";
            else
                commentEmail.name = "url";
        }
    },
    
    onPosted: function(event)
    {
        if (this.submittingPostId)
        {
            var commentProgress = $("commentEditorProgress");
            commentProgress.style.display = "none";
    
            this.submittingPostId = null;
            $("formSubmitter").src = "about:blank";
      }
    },
    
    ////////////////////////////////////////////////////////////////////////////////////////////////

    textToHTML: function(text)
    {
        var lines = text.split("\n");
        
        var html = "";
        for (var i in lines)
            html += "<p>" + lines[i] + "</p>";
        
        return html;
    },

    readXMLNodeValue: function(node, sourceNodeName)
    {
        var sourceNode = node.getElementsByTagName(sourceNodeName)[0];
        if (sourceNode.childNodes.length)
            return sourceNode.childNodes[0].nodeValue;
        else
            return "";
    }    
};

////////////////////////////////////////////////////////////////////////////////////////////////////

var LabeledInput = 
{
    apply: function(inputElt, defaultValue)
    {
        addListener(inputElt, "focus", this.onFocusInput, true);
        addListener(inputElt, "blur", this.onBlurInput, true);

        inputElt.defaultValue = defaultValue;
    
        if (inputElt.value == "" || inputElt.value == defaultValue)
        {
            addClass(inputElt, "empty");
            inputElt.value = defaultValue;
            return true;
        }  
    
        return false;
    },
    
    onFocusInput: function(event)
    {
        if (getEventTarget(event).nodeName == "INPUT" && hasClass(getEventTarget(event), "empty"))
        {
            getEventTarget(event).defaultValue = getEventTarget(event).value;
            getEventTarget(event).value = ""
            removeClass(getEventTarget(event), "empty");
        }
    },
    
    onBlurInput: function(event)
    {
        if (getEventTarget(event).nodeName == "INPUT" && getEventTarget(event).value == "")
        {
            getEventTarget(event).value = getEventTarget(event).defaultValue;
            addClass(getEventTarget(event), "empty");
        }
    }
};
