define(function (require, exports, module) {
    var oop = require("../lib/oop");
    var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
    var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

    var GolangHighlightRules = function () {
        var keywords = (
            "else|break|case|return|goto|if|const|select|" +
            "continue|struct|default|switch|for|range|" +
            "func|import|package|chan|defer|fallthrough|go|interface|map|range|" +
            "select|type|var"
        );
        var builtinTypes = (
            "string|uint8|uint16|uint32|uint64|int8|int16|int32|int64|float32|" +
            "float64|complex64|complex128|byte|rune|uint|int|uintptr|bool|error"
        );
        var builtinFunctions = (
            "new|close|cap|copy|panic|panicln|print|println|len|make|delete|real|recover|imag|append"
        );
        var builtinConstants = ("nil|true|false|iota");

        var keywordMapper = this.createKeywordMapper({
            "keyword": keywords,
            "constant.language": builtinConstants,
            "support.function": builtinFunctions,
            "support.type": builtinTypes
        }, "");

        var stringEscapeRe = "\\\\(?:[0-7]{3}|x\\h{2}|u{4}|U\\h{6}|[abfnrtv'\"\\\\])".replace(/\\h/g, "[a-fA-F\\d]");

        this.$rules = {
            "start": [
                {
                    token: "comment",
                    regex: "\\/\\/.*$"
                },
                DocCommentHighlightRules.getStartRule("doc-start"),
                {
                    token: "comment.start", // multi line comment
                    regex: "\\/\\*",
                    next: "comment"
                }, {
                    token: "string", // single line
                    regex: /"(?:[^"\\]|\\.)*?"/
                }, {
                    token: "string", // raw
                    regex: '`',
                    next: "bqstring"
                }, {
                    token: "constant.numeric", // rune
                    regex: "'(?:[^\\'\uD800-\uDBFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|" + stringEscapeRe.replace('"', '') + ")'"
                }, {
                    token: "constant.numeric", // hex
                    regex: "0[xX][0-9a-fA-F]+\\b"
                }, {
                    token: "constant.numeric", // float
                    regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
                }, {
                    token: ["keyword", "text", "entity.name.function"],
                    regex: "(func)(\\s+)([a-zA-Z_$][a-zA-Z0-9_$]*)\\b"
                }, {
                    token: function (val) {
                        if (val[val.length - 1] == "(") {
                            return [{
                                type: keywordMapper(val.slice(0, -1)) || "support.function",
                                value: val.slice(0, -1)
                            }, {
                                type: "paren.lparen",
                                value: val.slice(-1)
                            }];
                        }

                        return keywordMapper(val) || "identifier";
                    },
                    regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b\\(?"
                }, {
                    token: "keyword.operator",
                    regex: "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^="
                }, {
                    token: "punctuation.operator",
                    regex: "\\?|\\:|\\,|\\;|\\."
                }, {
                    token: "paren.lparen",
                    regex: "[[({]"
                }, {
                    token: "paren.rparen",
                    regex: "[\\])}]"
                }, {
                    token: "text",
                    regex: "\\s+"
                }
            ],
            "comment": [
                {
                    token: "comment.end",
                    regex: "\\*\\/",
                    next: "start"
                }, {
                    defaultToken: "comment"
                }
            ],
            "bqstring": [
                {
                    token: "string",
                    regex: '`',
                    next: "start"
                }, {
                    defaultToken: "string"
                }
            ]
        };

        this.embedRules(DocCommentHighlightRules, "doc-",
            [DocCommentHighlightRules.getEndRule("start")]);
    };
    oop.inherits(GolangHighlightRules, TextHighlightRules);

    exports.GolangHighlightRules = GolangHighlightRules;
});