Scribd.TagValidator = Class.create(Form.Element.Observer, {
    initialize: function($super, element, frequency) {
        $super(element, frequency, function(){  this.validate(); });
    },

    validate: function() {
        var tag_line = this.getValue();
        var tags = tag_line.split(',').map(function(t){return t.strip()})
        this.valid = true;
        this.validateMaxNumberOfTags(tags);
        this.validateMaxTagLength(tags);
        this.detectPotentialSeparatorMisuse(tags);
        if ( this.valid ) { this.element.fire('Scribd:tag_validator:valid'); }
    },

    validateMaxNumberOfTags: function(tags) {
        if ( tags.length > 20) {
            this.element.fire('Scribd:tag_validator:exceed_max_tags');
            this.valid = false;
        }
    },

    validateMaxTagLength: function(tags) {
        var oversized_tags = tags.select( function(tag) { 
            return tag.length > 60;
        });
        
        if ( oversized_tags.length > 0 ) {
            this.element.fire('Scribd:tag_validator:exceed_tag_length', {tags:oversized_tags});
            this.valid = false;
        }
    },

    detectPotentialSeparatorMisuse: function(tags) {
        // heuristic: no commas and having at least 3 tags
        if ( tags.length === 1 && tags[0].split(' ').without('').length >= 3 ) {
            this.element.fire('Scribd:tag_validator:space_for_comma');
            this.valid = false;
        }
    } 
});
Scribd.TagValidator.warning_event_names = ['space_for_comma', 'exceed_tag_length', 'exceed_max_tags'];


Scribd.TagValidator.ErrorHandler = Class.create({
    initialize: function(element, element_container) {
        this.element = $(element);
        this.element_container = $(element_container);
        this.element_container.insert(Scribd.TagValidator.ErrorHandler.warning_messages_html);
        this.message_container = this.element_container.down('.' + Scribd.TagValidator.ErrorHandler.warning_message_container_class);

        var error_handler = this;
        Scribd.TagValidator.warning_event_names.each(function(event_name) {
            var message_element = error_handler.message_container.down('.' + event_name); 
            error_handler['message_' + event_name] = message_element;
            // event listeners
            error_handler.element.observe("Scribd:tag_validator:" + event_name, function(event){
                if ( !message_element.visible() ) {
                    message_element.appear();
                }
            });

            // "fix it" handlers
            message_element.down('a').observe('click', function(event){
               event.stop();
               error_handler.element.setValue( Scribd.TagCleaner['clean_' + event_name](error_handler.element.getValue()) );
               if ( message_element.visible() ) {
                   message_element.fade();
               }
            });
        });

        // valid event listener
        this.element.observe('Scribd:tag_validator:valid', function(){
            Scribd.TagValidator.warning_event_names.each(function(event_name) {
                var message_element = error_handler['message_' + event_name];
                if ( message_element.visible() ) {
                    message_element.fade();
                }
            });
        });
    }
});


Scribd.TagValidator.ErrorHandler.warning_message_container_class = 'tag_validator_warning_messages';
Scribd.TagValidator.ErrorHandler.warning_messages_html = ' \
<ul class="tag_validator_warning_messages"> \
    <li class="space_for_comma" style="display:none"> \
        Did you forget to use commas to separate your tags? <a class="fix-commas" href="#">Yes, fix it for me.</a> \
    </li> \
    <li class="exceed_tag_length" style="display:none"> \
        Some tags have exceeded the maximum number of characters allowed (60 chars). They will be truncated if not removed. <a class="remove-long-tags" href="#" >Remove these tags for me.</a> \
    </li> \
    <li class="exceed_max_tags" style="display:none"> \
        You have exceeded the maximum number of tags allowed (20 tags). <a class="remove-exceeding-tags" href="#">Remove exceeding tags for me.</a> \
    </li> \
</ul>';


Scribd.TagCleaner = {
    clean_space_for_comma: function(tag_line) {
        if (tag_line.indexOf(',') === -1) {
            return tag_line.split(' ').without('').join(', ');
        } else {
            return tag_line;
        }
    },

    clean_exceed_tag_length: function(tag_line) {
        return tag_line.split(',').reject( function(tag){
            return tag.length > 60;
        }).join(',');
    },

    clean_exceed_max_tags: function(tag_line) {
        var tags = tag_line.split(',');
        if (tags.length > 20) {
            return tag_line.split(',').slice(0,20).join(',');
        } else {
            return tag_line;
        }
    }
}