// highly adapted for codemiror jshint

(function () {
    "use strict";
    function forEach(arr, f) {
        for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
    }
    
    function arrayContains(arr, item) {
        if (!Array.prototype.indexOf) {
            var i = arr.length;
            while (i--) {
                if (arr[i] === item) {return true;}
            }
            return false;
        }
        return arr.indexOf(item) != -1;
    }
    
    CodeMirror.contextHint = function(editor) {
        // Find the token at the cursor
        var cur = editor.getCursor(), token = editor.getTokenAt(cur), tprop = token;
        // If it's not a 'word-style' token, ignore the token.
        // If it is a property, find out what it is a property of.
        var list = new Array();
        var clist = getCompletions(token,editor);
        for(var i = 0 ; i < clist.length ; i++)
        {
            list.push(
                { str  : clist[i],
                  type : "context",
                  from : {line: cur.line, ch: token.start},
                  to   : {line: cur.line, ch: token.end} })
        }
        return list;
    }

    // find all 'words' of current cell
    var getAllTokens = function(editor)
    {
        var found = [];

        // add to found if not already in it
        function maybeAdd(str) {
            if (!arrayContains(found, str)) found.push(str);
        }

        // loop through all token on all lines
        var  lineCount = editor.lineCount();
        // loop on line
        for( var l=0; l< lineCount ; l++)
        {
            var line = editor.getLine(l);
            //loop on char
            for( var c = 1 ; c < line.length ; c++)
            {
                var tk = editor.getTokenAt({line:l,ch:c});
                // if token has a class, it has geat chances of beeing
                // of interest. Add it to the list of possible completions.
                // we could skip token of ClassName 'comment'
                // or 'number' and 'operator'
                if(tk.className != null){
                    maybeAdd(tk.string);
                }
                // jump to char after end of current token
                c = tk.end;
            }
        }
        return found;
    }


    function getCompletions(token,editor) 
    {
        var candidates = getAllTokens(editor);
        // filter all token that have a common start (but nox exactly) the lenght of the current token
        var lambda = function(x){ 
            return (x.indexOf(token.string)==0 && x != token.string)
            };
        var filterd = candidates.filter(lambda);
        return filterd;
    }
})();