(function() {

CodeMirror.xmlHints = [];

CodeMirror.xmlHint = function(cm, simbol) {

    if(simbol.length > 0) {
        var cursor = cm.getCursor();
        cm.replaceSelection(simbol);
        cursor = {line: cursor.line, ch: cursor.ch + 1};
        cm.setCursor(cursor);
    }

    CodeMirror.simpleHint(cm, getHint);
};

var getHint = function(cm) {

    var cursor = cm.getCursor();

    if (cursor.ch > 0) {

        var text = cm.getRange({line: 0, ch: 0}, cursor);
        var typed = '';
        var simbol = '';
        for(var i = text.length - 1; i >= 0; i--) {
            if(text[i] == ' ' || text[i] == '<') {
                simbol = text[i];
                break;
            }
            else {
                typed = text[i] + typed;
            }
        }

        text = text.slice(0, text.length - typed.length);

        var path = getActiveElement(cm, text) + simbol;
        var hints = CodeMirror.xmlHints[path];

        if(typeof hints === 'undefined')
            hints = [''];
        else {
            hints = hints.slice(0);
            for (var i = hints.length - 1; i >= 0; i--) {
                if(hints[i].indexOf(typed) != 0)
                    hints.splice(i, 1);
            }
        }

        return {
            list: hints,
            from: { line: cursor.line, ch: cursor.ch - typed.length },
            to: cursor
        };
    };
};

var getActiveElement = function(codeMirror, text) {

    var element = '';

    if(text.length >= 0) {

        var regex = new RegExp('<([^!?][^\\s/>]*).*?>', 'g');

        var matches = [];
        var match;
        while ((match = regex.exec(text)) != null) {
            matches.push({
                tag: match[1],
                selfclose: (match[0].slice(match[0].length - 2) === '/>')
            });
        }

        for (var i = matches.length - 1, skip = 0; i >= 0; i--) {

            var item = matches[i];

            if (item.tag[0] == '/')
            {
                skip++;
            }
            else if (item.selfclose == false)
            {
                if (skip > 0)
                {
                    skip--;
                }
                else
                {
                    element = '<' + item.tag + '>' + element;
                }
            }
        }

        element += getOpenTag(text);
    }

    return element;
};

var getOpenTag = function(text) {

    var open = text.lastIndexOf('<');
    var close = text.lastIndexOf('>');

    if (close < open)
    {
        text = text.slice(open);

        if(text != '<') {

            var space = text.indexOf(' ');
            if(space < 0)
                space = text.indexOf('\t');
            if(space < 0)
                space = text.indexOf('\n');

            if (space < 0)
                space = text.length;

            return text.slice(0, space);
        }
    }

    return '';
};

})();