/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

define(function (require, exports, module) {
    "use strict";

    var oop = require("../lib/oop");
    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
    var CssHighlightRules = require('./css_highlight_rules');

    var LessHighlightRules = function () {


        var keywordList = "@import|@media|@font-face|@keyframes|@-webkit-keyframes|@supports|" +
            "@charset|@plugin|@namespace|@document|@page|@viewport|@-ms-viewport|" +
            "or|and|when|not";

        var keywords = keywordList.split('|');

        var properties = CssHighlightRules.supportType.split('|');

        var keywordMapper = this.createKeywordMapper({
            "support.constant": CssHighlightRules.supportConstant,
            "keyword": keywordList,
            "support.constant.color": CssHighlightRules.supportConstantColor,
            "support.constant.fonts": CssHighlightRules.supportConstantFonts
        }, "identifier", true);

        // regexp must not have capturing parentheses. Use (?:) instead.
        // regexps are ordered -> the first match is used

        var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";

        // regexp must not have capturing parentheses. Use (?:) instead.
        // regexps are ordered -> the first match is used

        this.$rules = {
            "start": [
                {
                    token: "comment",
                    regex: "\\/\\/.*$"
                },
                {
                    token: "comment", // multi line comment
                    regex: "\\/\\*",
                    next: "comment"
                }, {
                    token: "string", // single line
                    regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
                }, {
                    token: "string", // single line
                    regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
                }, {
                    token: ["constant.numeric", "keyword"],
                    regex: "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
                }, {
                    token: "constant.numeric", // hex6 color
                    regex: "#[a-f0-9]{6}"
                }, {
                    token: "constant.numeric", // hex3 color
                    regex: "#[a-f0-9]{3}"
                }, {
                    token: "constant.numeric",
                    regex: numRe
                }, {
                    token: ["support.function", "paren.lparen", "string", "paren.rparen"],
                    regex: "(url)(\\()(.*)(\\))"
                }, {
                    token: ["support.function", "paren.lparen"],
                    regex: "(:extend|[a-z0-9_\\-]+)(\\()"
                }, {
                    token: function (value) {
                        if (keywords.indexOf(value.toLowerCase()) > -1)
                            return "keyword";
                        else
                            return "variable";
                    },
                    regex: "[@\\$][a-z0-9_\\-@\\$]*\\b"
                }, {
                    token: "variable",
                    regex: "[@\\$]\\{[a-z0-9_\\-@\\$]*\\}"
                }, {
                    token: function (first, second) {
                        if (properties.indexOf(first.toLowerCase()) > -1) {
                            return ["support.type.property", "text"];
                        }
                        else {
                            return ["support.type.unknownProperty", "text"];
                        }
                    },
                    regex: "([a-z0-9-_]+)(\\s*:)"
                }, {
                    token: "keyword",
                    regex: "&"   // special case - always treat as keyword
                }, {
                    token: keywordMapper,
                    regex: "\\-?[@a-z_][@a-z0-9_\\-]*"
                }, {
                    token: "variable.language",
                    regex: "#[a-z0-9-_]+"
                }, {
                    token: "variable.language",
                    regex: "\\.[a-z0-9-_]+"
                }, {
                    token: "variable.language",
                    regex: ":[a-z_][a-z0-9-_]*"
                }, {
                    token: "constant",
                    regex: "[a-z0-9-_]+"
                }, {
                    token: "keyword.operator",
                    regex: "<|>|<=|>=|=|!=|-|%|\\+|\\*"
                }, {
                    token: "paren.lparen",
                    regex: "[[({]"
                }, {
                    token: "paren.rparen",
                    regex: "[\\])}]"
                }, {
                    token: "text",
                    regex: "\\s+"
                }, {
                    caseInsensitive: true
                }
            ],
            "comment": [
                {
                    token: "comment", // closing comment
                    regex: ".*?\\*\\/",
                    next: "start"
                }, {
                    token: "comment", // comment spanning whole line
                    regex: ".+"
                }
            ]
        };
        this.normalizeRules();
    };

    oop.inherits(LessHighlightRules, TextHighlightRules);

    exports.LessHighlightRules = LessHighlightRules;

});
