/*global pluckArticleIds, pluckHandler, CN, console, window, alert, location, document, jQuery, setTimeout, clearTimeout, clearInterval, setInterval */ /* for jsLint */

CN.pluck = CN.pluck || {};
CN.pluck.plugin = CN.pluck.plugin || {};

/**
 * Plugin to add support for dynamically changing Pluck rating and commenting
 * Pluck markup must be present in CN.page.config, example below:
 * CN.page.config.pluckRatingMarkup = '<div class="rating"><div id="rating_' + CN.site.name + '_0000" class="rate">....etc
 * The _0000 is used as a placeholder to replace the div ids with the current item's
 *
 * @method      PluckHelper
 * @constructor
 * @requires    CN.pluck
 * @param       {Object} doc       A CN.IDoc instance to add pluck supporting
 * @param       {String} container A jQuery selector indicating the scoped container that has the Pluck div
 * @param       {String} crholder  A jQuery selector that immediately holds rating and commenting divs
*/
CN.pluck.plugin.PluckHelper = function(doc, container, crholder) {
    CN.Interface.ensureImplements(doc, CN.IDoc);
    this.doc             = doc;
    this.$pluckContainer = jQuery(container || 'body').find(crholder);
    this.hasInnerDiv     = this.$pluckContainer.find('.rating-comments').length === 1;
    this.hasRatingDiv    = this.$pluckContainer.find('.rating').length === 1;
    this.hasCommentDiv   = this.$pluckContainer.find('.comments').length === 1;
    this.site            = CN.site.name || '';
};

CN.pluck.plugin.PluckHelper.prototype = {

    /**
     * Regular expressions
     * @static
     * @private
     * @memberOf CN.pluck.PluckHelper
    */
    regex : {
        /**
         * Format for HTML id assigned to all the pluck elements
         * pixie_site_contentid_optionalcounter
         * @static
         * @private
        */
        id : /^(([A-Za-z]+_{1}[A-Za-z]+_{1})?([0-9]+){1}(_[0-9])?)/
    },

    /**
     * Called when slide changes to update Pluck rating and comments
     * @method   initNewDoc
     * @memberOf CN.pluck.PluckHelper
    */
    initNewDoc : function() {
        var newId,
            oldId,
            i,
            il,
            hasRatings  = false,
            hasComments = false;

                // Get out now if it's not going to work
        if (typeof pluckHandler === 'undefined' || !this.doc) {
            return;
        }

                // The content ID for the new slide
        newId = this.doc.getId();
                // Logic based on presence of comments/ratings, includes generating markup if necessary
        if (this.doc.hasComments()) {
            pluckHandler.crLogicHelper[this.site + '_' + newId] = 'C';
            hasComments = true;
            this.ensureCommentMarkup();
        } else {
            pluckHandler.crLogicHelper[this.site + '_' + newId] = '';
        }

        if (this.doc.hasRatings()) {
            pluckHandler.crLogicHelper[this.site + '_' + newId] += 'R';
            hasRatings = true;
            this.ensureRatingMarkup();
        }

        if(pluckHandler.crLogicHelper[this.site + '_' + newId] !== ''){
            pluckHandler.crMetaData[this.site + '_' + newId]={
                    title: this.doc.getTitle(),
                    type: this.doc.getDocType(),
                    kw: this.doc.getKeywords()
            };
        }
                // Sets the old ID, now that we know the markup is in the DOM with either a real or fake id
        oldId = this.getOldId();

                // Need to replace the entry in global pluckArticleIds. Not required or affected by slideshow.
        for (i = 0, il = pluckArticleIds.length; i < il; i++) {
            if (pluckArticleIds[i] === this.site + '_' + oldId) {
                pluckArticleIds[i] = this.site + '_' + newId;
            }
        }

                // Makes the ID changes to all the DOM elements // TODO: does this cover the id attached to report abuse link?
        this.replaceIds(newId);

                // Makes the Pluck request and initializes the form with the new ID
        pluckHandler.doArticleRequest(this.site + '_' + newId);
        pluckHandler.initCommentForm('frmSubmitComment_' + this.site + '_' + newId, this.site + '_' + newId, 'comments_' + this.site + '_' + newId, 'comment');

                // Whether or not we had a DCT slide, updates the display
        this.updateDisplay(hasComments, hasRatings);
    },

    /**
     * Changes visibility of Pluck rating and comment divs
     * @method updateDisplay
     * @param  {Boolean}     hasComments Does the current item have comments enabled?
     * @param  {Boolean}     hasRatings  Does the current item have ratings enabled?
    */
    updateDisplay : function(hasComments, hasRatings) {
        var el = this.$pluckContainer;
        el.removeClass('cr-noratings').removeClass('cr-nocomments').removeClass('cr-empty');
        if (!hasComments) {
            el.addClass('cr-nocomments');
        }
        if (!hasRatings) {
            el.addClass('cr-noratings');
        }
        if (!hasRatings && !hasComments) {
            el.addClass('cr-empty');
        }
    },

    /**
     * Gets the existing pluck ID
     * @method getOldId
     * @return {String} The existing pluck ID
    */
    getOldId : function() {
        var ret,
            that = this;

        this.$pluckContainer.find('[id^=comments_'  + CN.site.name + ']').each(function() {
            ret = this.id.match(that.regex.id)[3];
            return false;
        });

        return ret;
    },

    /**
     * Replaces the existing pluck ID with the new item's ID
     * for all elements within the container div
     * @method replaceIds
     * @param  {String}   newId The new item's pluck ID
    */
    replaceIds : function(newId) {
        var that = this;

        this.$pluckContainer.find('*').each(function() {
            if (this.id) {
                this.id = this.id.replace(that.regex.id, function($0, $1, $2, $3, $4) {
                    if (typeof $4 === 'undefined') { // webkit
                        $4 = '';
                    }
                    return $2 + newId + $4;
                });
            }
        });

        this.$pluckContainer.find('form').each(function() {
            if (this.name) {
                this.name = this.name.replace(that.regex.id, function($0, $1, $2, $3, $4) {
                    if (typeof $4 === 'undefined') { // webkit
                        $4 = '';
                    }
                    return $2 + newId + $4;
                });
            }
        });
    },

    /**
     * Checks to see if comment markup exists, and writes it if not.
     * Requires that CN.page.config contain pluckCommentMarkup
     * @method ensureCommentMarkup
    */
    ensureCommentMarkup : function() {
        var newMarkup;

        if (this.hasInnerDiv === false) {
            this.buildInnerDiv();
        }

        if (this.$pluckContainer.find('.comments').length === 0) {
            newMarkup = CN.page.config.pluckCommentMarkup || '';
            this.$pluckContainer.find('.rating-comments').append(newMarkup);
        }
    },

    /**
     * Checks to see if rating markup exists, and writes it if not.
     * Requires that CN.page.config contain pluckRatingMarkup
     * @method ensureRatingMarkup
    */
    ensureRatingMarkup : function() {
        var newMarkup;

        if (this.hasInnerDiv === false) {
            this.buildInnerDiv();
        }

        if (this.$pluckContainer.find('.rating').length === 0) {
            newMarkup = CN.page.config.pluckRatingMarkup || '';
            this.$pluckContainer.find('.rating-comments').prepend(newMarkup);
        }
    },

    /**
     * Builds the main comment div
     * @method buildInnerDiv
    */
    buildInnerDiv : function() {
        jQuery('<div id="comments_' + this.site + '_0000" class="rating-comments">').appendTo(this.$pluckContainer.children('div'));
        this.hasInnerDiv = true;
    }
};

