// CodeMirror, copyright (c) by Marijn Haverbeke and others

// Distributed under an MIT license: http://codemirror.net/LICENSE



(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("spreadsheet", function () {

    return {

      startState: function () {

        return {

          stringType: null,

          stack: []

        };

      },

      token: function (stream, state) {

        if (!stream) return;



        //check for state changes

        if (state.stack.length === 0) {

          //strings

          if ((stream.peek() == '"') || (stream.peek() == "'")) {

            state.stringType = stream.peek();

            stream.next(); // Skip quote

            state.stack.unshift("string");

          }

        }



        //return state

        //stack has

        switch (state.stack[0]) {

        case "string":

          while (state.stack[0] === "string" && !stream.eol()) {

            if (stream.peek() === state.stringType) {

              stream.next(); // Skip quote

              state.stack.shift(); // Clear flag

            } else if (stream.peek() === "\\") {

              stream.next();

              stream.next();

            } else {

              stream.match(/^.[^\\\"\']*/);

            }

          }

          return "string";



        case "characterClass":

          while (state.stack[0] === "characterClass" && !stream.eol()) {

            if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./)))

              state.stack.shift();

          }

          return "operator";

        }



        var peek = stream.peek();



        //no stack

        switch (peek) {

        case "[":

          stream.next();

          state.stack.unshift("characterClass");

          return "bracket";

        case ":":

          stream.next();

          return "operator";

        case "\\":

          if (stream.match(/\\[a-z]+/)) return "string-2";

          else {

            stream.next();

            return "atom";

          }

        case ".":

        case ",":

        case ";":

        case "*":

        case "-":

        case "+":

        case "^":

        case "<":

        case "/":

        case "=":

          stream.next();

          return "atom";

        case "$":

          stream.next();

          return "builtin";

        }



        if (stream.match(/\d+/)) {

          if (stream.match(/^\w+/)) return "error";

          return "number";

        } else if (stream.match(/^[a-zA-Z_]\w*/)) {

          if (stream.match(/(?=[\(.])/, false)) return "keyword";

          return "variable-2";

        } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) {

          stream.next();

          return "bracket";

        } else if (!stream.eatSpace()) {

          stream.next();

        }

        return null;

      }

    };

  });



  CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet");

});

