/* global CodeMirror */
(function (mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
        mod(require("../../lib/codemirror"));
    else if (typeof define == "function" && define.amd) // AMD
        define(["../../lib/codemirror"], mod);
    else // Plain browser env
        mod(CodeMirror);
})(function (CodeMirror) {
    "use strict";

    CodeMirror.defineMode("attributes", function () {

        var ON_NAMESPACE = 1;
        var ON_LOCALKEY = 2;
        var ON_VALUES = 3;
        var ON_COLON_OPERATOR = 4;
        var ON_EQUALITY_OPERATOR = 5;
        var ON_SEPARATOR_OPERATOR = 6;

        return {
            token: function (stream, state) {
                if (stream.sol()) {
                    state.position = ON_NAMESPACE;
                }
                if (stream.eatSpace()) {
                    return null;
                }
                if (state.position === ON_COLON_OPERATOR) {
                    stream.next();
                    state.position = ON_LOCALKEY;
                    return "operator";
                } else if (state.position === ON_EQUALITY_OPERATOR) {
                    stream.next();
                    state.position = ON_VALUES;
                    return "operator";
                } else if (state.position === ON_SEPARATOR_OPERATOR) {
                    stream.next();
                    state.position = ON_VALUES;
                    return "operator";
                } else if (state.position === ON_NAMESPACE) {
                    stream.eatWhile(/[^:=]/);
                    if ((!stream.eol()) && (stream.peek() === '=')) {
                        state.position = ON_EQUALITY_OPERATOR;
                        return "error";
                    }
                    state.position = ON_COLON_OPERATOR;
                    if (/^[_a-zA-Z]([-_.a-zA-Z0-9]*)$/.test(stream.current())) {
                        return "atom";
                    } else {
                        return "error";
                    }
                } else if (state.position === ON_LOCALKEY) {
                    stream.eatWhile(/[^=]/);
                    state.position = ON_EQUALITY_OPERATOR;
                    if (/^[_a-zA-Z]([-_.:/a-zA-Z0-9]*)(\s*)$/.test(stream.current())) {
                        return "def";
                    } else {
                        return "error";
                    }

                } else if (state.position === ON_VALUES) {
                    stream.eatWhile(/[^\\;]/);
                    if ((!stream.eol()) && (stream.peek() === '\\')) {
                        stream.next();
                        stream.next();
                    } else {
                        state.position = ON_SEPARATOR_OPERATOR;
                    }
                    return "quote";
                } else {
                    throw new Error("Unknown position: " + state.position);
                }
            },
            startState: function () {
                return {
                    position: ON_NAMESPACE
                };
            }

        };
    });

    CodeMirror.defineMIME("text/plain", "attributes");

});
