vanilla.comments = {
    _uuid             : '',
    _limit            : 20,
    _name_tmpl        : '&#8212; #{name}',
    _anonymous_name   : '&#8212; <em>Anonymous</em>',
    _prev_page_arrow  : '&#171; Previous',
    _next_page_arrow  : 'Next &#187;',
    _count_tmpl       : 'Viewing comments #{start}-#{stop} of #{count}',
    _container_id     : 'comments',
    _form_id          : 'comment_form',
    _indicator_class  : 'comment_indicator',
    _msgs_id          : 'comment_msgs',
    _errors_id        : 'comment_msgs',
    _list_id          : 'comment_list',
    _pager_header_id  : 'comment_pager_header',
    _pager_footer_id  : 'comment_pager_footer',
    _count_id         : 'comment_count',
    _preview_id       : 'comment_preview',
    _preview_title_id : 'comment_title_preview',
    _captcha_id       : 'comment_captcha',
    _max_length       : 500,
    _comment_tmpl     : '<div class="comment clearfix #{even_odd} #{first} #{nested_level_class}">'
        + '<div class="meta">#{created} #{gravatar_img}</div>'
        + '<div class="content">'
        + '<div class="title">#{title}</div>'
        + '#{content} #{name} #{reply_link}</div>'
        + '</div>',
    _content_msg_tmpl : '#{remain} characters left (#{max} characters allowed)',
    _content_warn_tmpl : '<span class="warn">#{remain} characters left</span> (#{max} characters allowed)',
    _content_msg_id   : 'content_msg',
    _reset_form       : true,
    _hide_form        : false,
    _use_gravatars    : true,
    _anon_gravatar    : null,
    _gravatar_tmpl    : '<img src="#{url}" width="40" height="40"></img>',
    _nested           : false,
    _reply_link_tmpl  : '<a class="reply_link" onclick="vanilla.comments._fill_reply_form(#{comment_id}, \'#{title}\')" href="#comment_form_anchor">[Reply]</a>',
    _extra_id         : '',
    _comment_filter   : function() {},
    _msgs             : {
        missing_email             : 'Please fill in your email address.',
        invalid_email             : 'That is not a valid email address.',
        missing_first_name        : 'Please fill in your First Name.',
        invalid_first_name        : 'Your First Name is too long. Please keep it under 255 characters.',
        invalid_last_name         : 'Your Last Name is too long. Please keep it under 255 characters.',
        invalid_title             : 'Your Title is too long. Please keep it under 255 characters.',
        missing_content           : 'Please enter your comments content.',
        invalid_comment_too_long  : 'We\'re sorry but that comment is too long.',
        invalid_comment_profanity : 'We\'re sorry but we do not allow profanity in our comments.',
        require_approval          : 'Your comment has been saved and will appear when it has been approved.',
        require_login             : 'We\'re sorry but you must be logged in to post a comment.',
        approved                  : 'Your comment has been posted.',
        comments_closed           : 'We\'re sorry but this article is closed for future comments.',
        comments_disabled         : 'Comments are no longer being accepted on this article.',
        comments_limit_reached    : 'We\'re sorry but the limit has been reached to number of comments for this article.',
        invalid_comment_spam      : 'That comment looks like spam!',
        spam_potential            : 'That comment looks like spam. Please type the letters you see below in order to submit your post.',
        captcha_incorrect         : 'That solution is incorrect. Please try again or get a new image.',
        duplicate_comment         : 'That comment has already been added.',
        user_ban                  : 'We\'re sorry. You have been banned from posting comments on this site.',
        ajax_error                : 'We\'re sorry. There was a problem submitting your comment. Please come back and try again later.',
        not_available             : 'We\'re sorry. Comments are temporarily unavailable. Please come back and try again later.'
    },
    _current_page     : 1,
    _total            : 0,
    _date_format : '%m/%d/%Y<br>%l:%M %p',
    _date_locale : 'en',
    _allow_formatting : 0,
    _max_nested_level : 10,
    _preview          : false,

    // class methods

    init : function(args) {
        for(var arg in args) {
            // msgs is a hash that should only have to override the msgs it wants to
            if( arg == 'msgs' ) {
                for(var key in args['msgs'] ) {
                    vanilla.comments['_msgs'][key] = args['msgs'][key];
                }
            } else {
                vanilla.comments['_' + arg] = args[arg];
            }
        }
        
        // set up our Markdown converter for later
        if( vanilla.comments._allow_formatting ) {
            vanilla.comments._markdown_converter = new Showdown.converter();
        }

        jQuery(document).ready(function() {
            // check to see if comments are enabled on this page
            var url = '/api/c/options/' + vanilla.comments._uuid;
            var now = new Date().valueOf();
            // use jQuery.ajax() here instead of jQuery.get() so that we can catch 404 errors
            jQuery.ajax({
                type: 'GET',
                url: url,
                dataType: 'json',
                cache : false,
                error : function(request, status, error) {
                    var message;
                    var className;
                    if( request.status == '404' ) {
                        message = 'not_available';
                    } else {
                        message = 'ajax_error';
                    }
                    jQuery('#' + vanilla.comments._container_id).html('<p>' + vanilla.comments._msgs[message] + '</p>').addClass(message).show();
                    vanilla.comments._hide_indicator();
                },
                success : function(results, textStatus) {
                    if( results.enable || vanilla.comments._preview ) {
                        jQuery('#' + vanilla.comments._container_id).show();
                        // set up our form to submit the comment
                        jQuery('#' + vanilla.comments._form_id).submit(vanilla.comments.post);

                        // show any existing comments
                        vanilla.comments.show();

                        // if we have any data on this person from any last actions, lets fill it in
                        var last_action_data = vanilla.last_action_data();
                        if( last_action_data ) {
                            jQuery('#' + vanilla.comments._form_id + ' input[name=email]').val(last_action_data.email);
                            jQuery('#' + vanilla.comments._form_id + ' input[name=first_name]').val(last_action_data.first_name);
                            jQuery('#' + vanilla.comments._form_id + ' input[name=last_name]').val(last_action_data.last_name);
                        }

                        // setup a handler for any errors
                        jQuery('#' + vanilla.comments._errors_id).ajaxError(function(ev, request, settings) {
                            jQuery(this).html('<p>' + vanilla.comments._msgs['ajax_error'] + '</p>').show();
                            vanilla.comments._hide_indicator();
                        });

                        // setup the content field for it's message
                        vanilla.text_counter({
                            field_selector   : '#' + vanilla.comments._form_id + ' textarea[name=content]',
                            max_length       : vanilla.comments._max_length,
                            message_selector : '#' + vanilla.comments._content_msg_id,
                            message_template : vanilla.comments._content_msg_tmpl,
                            warn_template    : vanilla.comments._content_warn_tmpl
                        });

                        // show if we already have something
                        vanilla.comments._update_content_preview();
                        
                        // event handler to handle changes as they type their content
                        jQuery('#' + vanilla.comments._form_id + ' textarea[name=content]').keyup(function(event) { 
                            vanilla.comments._update_content_preview();
                        });
                        
                        // setup the title field for it's message
                        if(vanilla.comments._allow_formatting) {
                            vanilla.comments._update_title_preview();

                            // event handler to handle changes as they type their title
                            jQuery('#' + vanilla.comments._form_id + ' input[name=title]').keyup(function(event) {
                                vanilla.comments._update_title_preview();
                            });

                            // to handle copy-paste of either the Title or the body, we should update the preview
                            // every second, just in case it's changed by not via a keyup event
                            vanilla.comments._interval_handler = window.setInterval(function() {
                                vanilla.comments._update_content_preview();
                                vanilla.comments._update_title_preview();
                            }, 1000); 

                            // new captcha image button
                            jQuery('#submit_new_image').click(function() {
                                jQuery('#' + vanilla.comments._captcha_id + ' input[name=captcha_solution]').val('');
                                return true;
                            });
                        }
                    } else {
                        jQuery('#' + vanilla.comments._container_id).hide();
                    }
                }
            });
        });
    },

    post : function(event) {
        event.preventDefault();
        vanilla.comments._show_indicator();
        jQuery.post('/api/c/' + vanilla.comments._uuid, jQuery('#' + vanilla.comments._form_id).serialize(), function(results) { 
            vanilla.comments._hide_indicator();
            if(results.success) {
                var msg = results.require_approval ? vanilla.comments._msgs['require_approval'] : vanilla.comments._msgs['approved'];
                jQuery('#' + vanilla.comments._msgs_id).html(msg).show();
                jQuery('#' + vanilla.comments._form_id + ' input[name=parent_id]').val('');
                if( vanilla.comments._reset_form ) {
                    // jQuery('#' + vanilla.comments._form_id).each(function() { this.reset() });
                    jQuery('#' + vanilla.comments._form_id + ' input[name=title]').val('');
                    jQuery('#' + vanilla.comments._form_id + ' textarea[name=content]').each(function() {
                        this.value = '';
                    });
                    jQuery('#' + vanilla.comments._preview_id).html('');
                    jQuery('#' + vanilla.comments._preview_title_id).html('');
                }
                if( vanilla.comments._hide_form ) {
                    jQuery('#' + vanilla.comments._form_id).hide();
                }
                jQuery('#' + vanilla.comments._captcha_id).hide();
                vanilla.comments.show(true, true);

                // clear out any timed interval functions we have
                if ( vanilla.comments._interval_handler && vanilla.comments._hide_form) {
                    window.clearInterval(vanilla.comments._interval_handler);
                }
            } else {
                if( results.error == 'spam_potential' ) {
                    // we need to show a captcha
                    jQuery('#' + vanilla.comments._captcha_id).show();
                    jQuery('#' + vanilla.comments._captcha_id + ' img.captcha').each(function() { this.src = results.captcha_url });
                    jQuery('#' + vanilla.comments._captcha_id + ' input[name=captcha_solution]').each( function() { this.value = '' });
                    jQuery('#' + vanilla.comments._captcha_id + ' input[name=new_captcha]').each( function() { this.value = 0 });
                }
                jQuery('#' + vanilla.comments._msgs_id).hide();
                var error_msg = vanilla.comments._msgs[results.error] || results.error;
                jQuery('#' + vanilla.comments._errors_id).html(error_msg).show();
            }
        }, "json");
    },

    show : function(goto_end, no_cache) {
        var url = '/api/c/' + vanilla.comments._uuid;
        var request_args = {
            count    : 1,
            extra_id : vanilla.comments._extra_id
        };
        if( no_cache ) {
            request_args['no_cache'] = 1;
        } else {
            request_args['buster'] = new Date().valueOf();
        }

        jQuery.get(url, request_args, function(results) {
            var total = results.count;
            vanilla.comments._total = total;

            // if we have anything then show it
            if(total > 0 ) {
                vanilla.comments._show_indicator();

                // update the pager now that we know how many there are
                vanilla.comments._update_pager(goto_end);

                // calculate the offset from the page number
                var offset = vanilla.comments._limit * (vanilla.comments._current_page - 1);
                request_args['count']  = 0;
                request_args['limit']  = vanilla.comments._limit;
                request_args['offset'] = offset;
                jQuery.get(url, request_args, function(results) {
                        vanilla.comments._process_comments(results);
                        vanilla.comments._hide_indicator();
                        if (goto_end) {
                            jQuery("html:not(:animated),body:not(:animated)").animate(
                                { scrollTop: jQuery('#' + vanilla.comments._msgs_id).offset().top}, 
                                10 
                            );
                        }
                    }, 
                    'json'
                );
            }
        }, 'json');
    },

    next_page  : function() {
        vanilla.comments._current_page = vanilla.comments._current_page + 1;
        vanilla.comments.show();
    },

    prev_page  : function() {
        vanilla.comments._current_page = vanilla.comments._current_page - 1;
        vanilla.comments.show();
    },

    page       : function(page_no) {
        vanilla.comments._current_page = page_no;
        vanilla.comments.show();
    },

    _process_comments : function(comments) {
        var container = jQuery('#' + vanilla.comments._list_id).html(''); // clear out the container
        for(var i in comments) {
            var comment = comments[i];
            vanilla.comments._comment_filter(comment);
            
            // filter the user data to prevent XSS
            var name = vanilla.escape_html(comment.username);
            if(!name) name = vanilla.escape_html(comment.name);
            if(name && comment.person_id) {
                // if we have a name use the name template to format it
                name = vanilla.template(
                    vanilla.comments._name_tmpl, 
                    { name : name, username_url: encodeURIComponent(comment.username), person_id : comment.person_id }
                );
            } else {
                name = vanilla.comments._anonymous_name;
            }
            comment.name = name;
            comment.title = vanilla.escape_html(comment.title) || '';
            if( !vanilla.comments._allow_formatting ) comment.content = vanilla.escape_html(comment.content);

            // handle the created date
            comment.created = vanilla.strftime(
                vanilla.comments._date_format, 
                new Date(comment.created * 1000),
                vanilla.comments._date_locale
            );
            comment.i = vanilla.format_number(parseInt(i) + 1 + ((vanilla.comments._current_page - 1) * vanilla.comments._limit));
            comment.even_odd = (parseInt(i) + 1) % 2 == 0 ? 'even' : 'odd';
            comment.first = (i == 0) ? 'first' : '';

            // create the gravatar_img if we want to
            comment.gravatar_img = '';
            if( vanilla.comments._use_gravatars ) {
                if( comment.email_hash ) {
                    comment.gravatar_img = vanilla.template(
                        vanilla.comments._gravatar_tmpl,
                        { url : vanilla.gravatar_url(comment.email_hash, { size: 40, hash: 0 }) }
                    );
                } else if( vanilla.comments._anon_gravatar ) {
                    comment.gravatar_img = vanilla.template(
                        vanilla.comments._gravatar_tmpl,
                        { url : vanilla.comments._anon_gravatar }
                    );
                }
            }

            // nested comments need a reply link per-comment
            if( vanilla.comments._nested ) {
                comment.reply_link = vanilla.template(
                    vanilla.comments._reply_link_tmpl, 
                    { 
                        title      : vanilla.escape_js(comment.title), 
                        comment_id : comment.comment_id
                    }
                );
                if( comment.level == 0 ) {
                    comment.nested_level_class = '';
                } else if( comment.level > vanilla.comments._max_nested_level ) {
                    comment.nested_level_class = 'nested level_' + vanilla.comments._max_nested_level;
                    comment.level = vanilla.comments._max_nested_level;
                } else { 
                    comment.nested_level_class = 'nested level_' + comment.level;
                }
            } else {
                comment.reply_link = '';
                comment.nested_level_class = '';
                comment.level = 0;
            }

            // use the comments template with all this data now
            container.append(vanilla.template(vanilla.comments._comment_tmpl, comment));
        }
    },

    _update_pager : function(goto_end) {
        var limit           = vanilla.comments._limit;
        var total           = vanilla.comments._total;
        var last_page       = Math.ceil(total / limit);
        var current_page    = goto_end ? last_page : vanilla.comments._current_page;
        
        vanilla.comments._current_page = current_page;

        // update the count section
        var start = limit * (current_page -1) + 1;
        var stop  = limit * current_page;
        if( stop > total ) stop = total;
        
        jQuery('#' + vanilla.comments._count_id).html(
            vanilla.template(
                vanilla.comments._count_tmpl, 
                { 
                    count : vanilla.format_number(total),
                    start : vanilla.format_number(start), 
                    stop  : vanilla.format_number(stop)
                }
            )
        );

        var pager_output = '';
        if( last_page > 1 ) {
            // create the list of page links
            if( current_page == 1 ) {
                pager_output += vanilla.comments._prev_page_arrow + '&#160;&#160;';
            } else {
                pager_output += '<a href="javascript:vanilla.comments.prev_page()">' 
                  + vanilla.comments._prev_page_arrow 
                  + '</a>'
                  + '&#160;&#160;';
            }
            for(var i=1; i<=last_page; i++) {
                if( i == current_page ) {
                    pager_output += i;
                } else {
                    pager_output += '<a href="javascript:vanilla.comments.page(' + i + ')">' + i + '</a>';
                }
                if(last_page != i ) pager_output += ', ';
            }
            if( current_page == last_page ) {
                pager_output += '&#160;&#160;' + vanilla.comments._next_page_arrow;
            } else {
                pager_output += '&#160;&#160;'
                  + '<a href="javascript:vanilla.comments.next_page()">' 
                  + vanilla.comments._next_page_arrow 
                  + '</a>';
            }
            jQuery('#' + vanilla.comments._pager_header_id).html(pager_output);
            jQuery('#' + vanilla.comments._pager_footer_id).html(pager_output);
        }
    },

    _update_content_preview : function() {
        // setup the formatting preview if we are allowing that
        if(vanilla.comments._allow_formatting) {
            jQuery('#' + vanilla.comments._form_id + ' textarea[name=content]').each(function() {
                if( this.value ) {
                    var formatted_content = vanilla.comments._markdown_converter.makeHtml(this.value);
                    jQuery('#' + vanilla.comments._preview_id).html(formatted_content);
                }
            });
        }
    },

    _update_title_preview : function() {
        if( vanilla.comments._allow_formatting ) {
            jQuery('#' + vanilla.comments._form_id + ' input[name=title]').each(function() {
                // show if we already have something
                if (this.value) {
                    jQuery('#' + vanilla.comments._preview_title_id).html(vanilla.escape_html(this.value)).show();
                }    
            });
        }
    },

    _fill_reply_form : function(parent_id, title) {
        jQuery('#' + vanilla.comments._form_id).each( function() { 
            this.elements['parent_id'].value = parent_id;
            this.elements['title'].value = 'Re: ' + title;
        });
    },

    _show_indicator : function() {
        jQuery('#' + vanilla.comments._form_id + ' .submit').addClass(vanilla.comments._indicator_class);
    }, 

    _hide_indicator : function() {
        jQuery('#' + vanilla.comments._form_id + ' .submit').removeClass(vanilla.comments._indicator_class);
    }
};


