/* <copyright>
 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
 (c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
 </copyright> */
/**
	@module "montage/ui/rich-text-sanitizer.js"
    @requires montage/core/core
*/
var Montage = require("montage").Montage;

/**
    @class module:"montage/ui/rich-text-sanitizer.js".Sanitizer
    @extends module:montage/core/core.Montage
*/
exports.Sanitizer = Montage.create(Montage,/** @lends module:"montage/ui/rich-text-sanitizer.js".Sanitizer# */ {

    willSetValue: {
        value: function(value, identifier)  {
            return this._scopeCSS(value, identifier);
        }
    },

    didGetValue: {
        value: function(value, identifier)  {
            return this._unscopeCSS(value, identifier);
        }
    },

    willInsertHTMLData: {
        value: function(data, identifier)  {
            return this._scopeCSS(this._removeScript(data), identifier);
        }
    },

    _scopeCSS: {
        enumerable: true,
        value: function(htmlFragment, identifier) {
            var identifierSelector = ".editor-" + identifier+ " ";

            if (typeof htmlFragment == "string") {
                // Extract the style tag and its content
                htmlFragment = htmlFragment.replace(/(<style ?[^>]*>)([^<]*)(<\/style>)/ig, function(match, pre, style, post) {
                    // Remove any newlines and tab for easier processing
                    style = style.replace(/\t|\n|\r/g, function(char) {if (char == "\t") return " "; return ""});

                    // Cleanup any potential leftover from a previous scoping
                    style = style.replace(/\*\.editor-[^ ] +/g, "body");
                    style = style.replace(/\.editor-[^ ]+ /g, "");

                    // Extract the selectors for each css block
                    style = style.replace(/([^{]+)({[^}]*})/ig, function(match, selectors, rules) {

                        // Split the selectors and add the identifierSelector
                        selectors = selectors.replace(/ *([^,]+)/g, function(match, selector) {
                            // convert body selector
                            if (selector.toLowerCase() == "body") {
                                return "*" + identifierSelector;
                            } else {
                                return identifierSelector + selector;
                            }
                        })
                        return selectors + rules;
                    })
                    return pre + style + post;
                });
            }

            return htmlFragment;
        }
    },

    _unscopeCSS: {
        enumerable: true,
        value: function(htmlFragment, identifier) {

            if (typeof htmlFragment == "string") {
                // Extract the style tag and its content
                htmlFragment = htmlFragment.replace(/(<style ?[^>]*>)([^<]*)(<\/style>)/ig, function(match, pre, style, post) {
                    style = style.replace(/\*\.editor-[^ ] +/g, "body");
                    style = style.replace(/\.editor-[^ ]+ /g, "");
                    return pre + style + post;
                });
            }
            return htmlFragment;
        }
    },

    _removeScript: {
        enumerable: true,
        value: function(htmlFragment) {
            /*
                Will remove any script tag, onXXX handlers and javascript URLs
             */
            var div = document.createElement("div"),
                _removeScript = function(element) {
                    var children = element.children,
                        child,
                        nbrChildren = children.length,
                        attributes = element.attributes,
                        attribute,
                        nbrAttributes = attributes.length,
                        i;

                for (i = 0; i < nbrAttributes; i ++) {
                    attribute = attributes[i];
                    if (attribute.name.match(/^on[a-z]+/i) || attribute.value.match(/^javascript:/)) {
                        element.removeAttribute(attribute.name);
                        i --;
                        nbrAttributes --;
                    }
                }

                for (i = 0; i < nbrChildren; i ++) {
                    child = children[i];
                    if (child.tagName == "SCRIPT") {
                        child.parentNode.removeChild(child);
                        i --;
                        nbrChildren --;
                    } else {
                        _removeScript(child);
                    }
                }
            };

            div.innerHTML = htmlFragment;
            _removeScript(div);

            return div.innerHTML;
        }
    }
});