var DomUtils = require(“domutils”),

hasAttrib = DomUtils.hasAttrib,
getAttributeValue = DomUtils.getAttributeValue,
falseFunc = require("boolbase").falseFunc;

//https://github.com/slevithan/XRegExp/blob/master/src/xregexp.js#L469 var reChars = /[-[]{}()*+?.,\^$|#s]/g;

/*

attribute selectors

*/

var attributeRules = {

__proto__: null,
equals: function(next, data){
        var name  = data.name,
            value = data.value;

        if(data.ignoreCase){
                value = value.toLowerCase();

                return function equalsIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null && attr.toLowerCase() === value && next(elem);
                };
        }

        return function equals(elem){
                return getAttributeValue(elem, name) === value && next(elem);
        };
},
hyphen: function(next, data){
        var name  = data.name,
            value = data.value,
            len = value.length;

        if(data.ignoreCase){
                value = value.toLowerCase();

                return function hyphenIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null &&
                                        (attr.length === len || attr.charAt(len) === "-") &&
                                        attr.substr(0, len).toLowerCase() === value &&
                                        next(elem);
                };
        }

        return function hyphen(elem){
                var attr = getAttributeValue(elem, name);
                return attr != null &&
                                attr.substr(0, len) === value &&
                                (attr.length === len || attr.charAt(len) === "-") &&
                                next(elem);
        };
},
element: function(next, data){
        var name = data.name,
            value = data.value;

        if(/\s/.test(value)){
                return falseFunc;
        }

        value = value.replace(reChars, "\\$&");

        var pattern = "(?:^|\\s)" + value + "(?:$|\\s)",
            flags = data.ignoreCase ? "i" : "",
            regex = new RegExp(pattern, flags);

        return function element(elem){
                var attr = getAttributeValue(elem, name);
                return attr != null && regex.test(attr) && next(elem);
        };
},
exists: function(next, data){
        var name = data.name;
        return function exists(elem){
                return hasAttrib(elem, name) && next(elem);
        };
},
start: function(next, data){
        var name  = data.name,
            value = data.value,
            len = value.length;

        if(len === 0){
                return falseFunc;
        }

        if(data.ignoreCase){
                value = value.toLowerCase();

                return function startIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null && attr.substr(0, len).toLowerCase() === value && next(elem);
                };
        }

        return function start(elem){
                var attr = getAttributeValue(elem, name);
                return attr != null && attr.substr(0, len) === value && next(elem);
        };
},
end: function(next, data){
        var name  = data.name,
            value = data.value,
            len   = -value.length;

        if(len === 0){
                return falseFunc;
        }

        if(data.ignoreCase){
                value = value.toLowerCase();

                return function endIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null && attr.substr(len).toLowerCase() === value && next(elem);
                };
        }

        return function end(elem){
                var attr = getAttributeValue(elem, name);
                return attr != null && attr.substr(len) === value && next(elem);
        };
},
any: function(next, data){
        var name  = data.name,
            value = data.value;

        if(value === ""){
                return falseFunc;
        }

        if(data.ignoreCase){
                var regex = new RegExp(value.replace(reChars, "\\$&"), "i");

                return function anyIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null && regex.test(attr) && next(elem);
                };
        }

        return function any(elem){
                var attr = getAttributeValue(elem, name);
                return attr != null && attr.indexOf(value) >= 0 && next(elem);
        };
},
not: function(next, data){
        var name  = data.name,
            value = data.value;

        if(value === ""){
                return function notEmpty(elem){
                        return !!getAttributeValue(elem, name) && next(elem);
                };
        } else if(data.ignoreCase){
                value = value.toLowerCase();

                return function notIC(elem){
                        var attr = getAttributeValue(elem, name);
                        return attr != null && attr.toLowerCase() !== value && next(elem);
                };
        }

        return function not(elem){
                return getAttributeValue(elem, name) !== value && next(elem);
        };
}

};

module.exports = {

compile: function(next, data, options){
        if(options && options.strict && (
                data.ignoreCase || data.action === "not"
        )) throw SyntaxError("Unsupported attribute selector");
        return attributeRules[data.action](next, data);
},
rules: attributeRules

};