/* global Bdf */

Bdf.Ficheblock = {};

Bdf.Ficheblock.ZONE_STANDARD = 0;
Bdf.Ficheblock.ZONE_TABLE = 1;
Bdf.Ficheblock.ZONE_CODE = 2;
Bdf.Ficheblock.ZONE_CDATADIV = 3;
Bdf.Ficheblock.ZONE_INSERT = 4;

Bdf.Ficheblock.checkEnabled = function (codeMirror) {
    var enabled = {
        always: true,
        blank: false,
        heading: false,
        list: false,
        text: false
    };
    let historySize = codeMirror.historySize();
    enabled.undo =  (historySize.undo > 0);
    enabled.redo = (historySize.redo > 0);
    let cursor = codeMirror.getCursor();
    let line = codeMirror.getLine(cursor.line);
    if (line.length === 0) {
        if (cursor.line === 0) {
            enabled.blank = true;
            enabled.heading = true;
            enabled.text = true;
        } else {
            let state = codeMirror.getStateAfter(cursor.line - 1);
            if (_onZoneStandard(state)) {
                enabled.heading = true;
                if (state.onDiv === 0) {
                    enabled.blank = true;
                }
            }
            enabled.text = _onText(state);
        }
    } else {
        let stateAtCursor;
        if (cursor.ch < (line.length - 1)) {
            stateAtCursor = codeMirror.getTokenAt({
                ch: (cursor.ch + 1),
                line: cursor.line
            }).state;
        } else {
            stateAtCursor = codeMirror.getTokenAt(cursor).state;
        }
        if (_onZoneStandard(stateAtCursor)) {
            if (stateAtCursor.contentType === "standard") {
                if (!stateAtCursor.hasSource) {
                    enabled.heading = true;
                }
                enabled.list = true;
            } else if ((stateAtCursor.contentType === "li-first") || (stateAtCursor.contentType === "li-next")) {
                enabled.list = true;
            }
        }
        enabled.text = _onText(stateAtCursor);
    }
    if (codeMirror.somethingSelected()) {
        enabled.blank = false;
        enabled.heading = false;
        enabled.text = false;
    }
    enabled.selection = Bdf.Ficheblock.checkSelection(codeMirror);
    return enabled;
    
    function _onZoneStandard(state) {
        return (state.currentZone ===  Bdf.Ficheblock.ZONE_STANDARD);
    }
    
    function _onText(state) {
        switch(state.currentZone) {
            case Bdf.Ficheblock.ZONE_STANDARD:
            case Bdf.Ficheblock.ZONE_TABLE:
                return true;
            default:
                return false;
        }
    }
};

Bdf.Ficheblock.checkSelection = function (codeMirror) {
    if (!codeMirror.somethingSelected()) {
        return false;
    }
    if (codeMirror.getSelections().length > 1) {
        return false;
    }
    let fromCursor = codeMirror.getCursor("from");
    let toCursor = codeMirror.getCursor("to");
    if (fromCursor.line !== toCursor.line) {
        return false;
    }
    let token = codeMirror.getTokenAt(toCursor);
    if (token.start > fromCursor.ch) {
        return false;
    }
    if (!token.type) {
        return true;
    }
    switch(token.type) {
        case "ficheblock-hcontent":
        case "line-ficheblock-div":
        case "ficheblock-tablecontent":
        case "ficheblock-zone-elementcontent":
            return true;
        default:
            return false;
    }
};

Bdf.Ficheblock.escapeValue = function (value) {
    if (_needsQuote()) {
        let result = '"';
        for (let i = 0, len = value.length; i < len; i++) {
            let carac = value.charAt(i);
            if (carac === '"') {
                result += '\\"';
            } else if (carac === '\\') {
                result +=  "\\\\";
            } else {
                result += carac;
            }
        }
        result += '"';
        return result;
    } else {
        return value;
    }
    
    
    function _needsQuote() {
        for (let i = 0, len = value.length; i < len; i++) {
            switch (value.charAt(i)) {
                case ' ':
                case '\"':
                case ')':
                case '=':
                    return true;
            }
        }
        return false;
    }
    
};

Bdf.Ficheblock.getStartSequence = function (zonetype) {
    switch(zonetype) {
        case "table":
            return "===";
        case "insert":
        case "insert_image":
        case "insert_audio":
            return ":::";
        case "code":
            return "+++";
        case "div":
            return "!!!";
        case "cdata":
            return "???";
        default:
            return "";
    }
};

Bdf.Ficheblock.getEndSequence = function (zonetype) {
    switch(zonetype) {
        case "table":
            return "===========";
        case "insert":
        case "insert_image":
        case "insert_audio":
            return ":::::::::::";
        case "code":
            return "+++++++++++";
        case "div":
            return "!!!!!!!!!!!";
        case "cdata":
            return "???????????";
        default:
            return "";
    }
};

Bdf.Ficheblock.insertCharsAtStart = function (codeMirror, chars)  {
    let cursor = codeMirror.getCursor();
    let insertPosition = 0;
    let line = codeMirror.getLine(cursor.line);
    if (line.trim().length > 0) {
        insertPosition = line.length - 1;
        let array = codeMirror.getLineTokens(cursor.line);
        for(let i = 0, len = array.length; i < len; i++) {
            let token = array[i];
            if (token.state.contentType === "standard") {
                insertPosition = token.start;
                break;
            }
        }
    }
    if ((insertPosition > 0) && (line.charAt(insertPosition -1) !== ' ')) {
        chars = " " + chars;
    }
    codeMirror.replaceRange(chars, {line: cursor.line,ch: insertPosition});
    codeMirror.focus();
};

Bdf.Ficheblock.insertList = function (codeMirror)  {
    var insertArray = new Array();
    if (codeMirror.somethingSelected()) {
        let list = codeMirror.listSelections();
        for(let i = 0, len = list.length; i < len; i++) {
            let selection = list[i];
            let startNumber, endNumber;
            if (selection.anchor.line > selection.head.line) {
                startNumber = selection.head.line;
                endNumber = selection.anchor.line;
            } else {
                startNumber = selection.anchor.line;
                endNumber = selection.head.line;
            }
            for(let j = startNumber; j <= endNumber; j++) {
                let insert = _insertInLine(j);
                if (insert) {
                    insertArray.push(insert);
                }
            }
        }
    } else {
        let insert = _insertInLine(codeMirror.getCursor().line);
        if (insert) {
            insertArray.push(insert);
        }
    }
    for(let i = 0, len = insertArray.length; i < len; i++) {
        let insert = insertArray[i];
        let cursor = {line: insert.line,ch: insert.position};
        let chars = insert.char;
        if (insert.spaceBefore) {
            chars = " " + chars;
        }
        if (insert.spaceAfter) {
            chars = chars + " ";
        }
        codeMirror.replaceRange(chars, cursor, cursor, "+overlay");
    }
    codeMirror.focus();
    
    
    function _checkPosition(char, string) {
        for(let i = 0, len = string.length; i < len; i++) {
            if (string.charAt(i) === char) {
                return i;
            }
        }
        return 0;
    }
    
    function _insertInLine(lineNumber) {
        let insertPosition = -1;
        let insertChar;
        let line = codeMirror.getLine(lineNumber);
        if (line.length > 0) {
            let array = codeMirror.getLineTokens(lineNumber);
            for(let i = 0, len = array.length; i < len; i++) {
                let token = array[i];
                if (token.state.contentType === "standard") {
                    insertChar = '-';
                    insertPosition = token.start;
                    break;
                } else if (token.state.contentType === "li-first") {
                    insertPosition = token.start + _checkPosition('-', token.string);
                    insertChar = '-';
                    break;
                } else if (token.state.contentType === "li-next") {
                    insertPosition = token.start + _checkPosition('-', token.string);
                    insertChar = '_';
                    break;
                }
            }
        }
        if (insertPosition === -1) {
            return null;
        }
        let spaceBefore = false;
        let spaceAfter = false;
        if (insertPosition > 0) {
            if (line.charAt(insertPosition -1) !== ' ') {
                spaceBefore = true;
           }
        }
        if (insertPosition < (line.length - 1)) {
            var afterChar = line.charAt(insertPosition + 1);
            if ((afterChar !== ' ') && (afterChar !== insertChar)) {
                spaceAfter = true;
            }
        }
        return {
            line: lineNumber,
            position: insertPosition,
            char: insertChar,
            spaceBefore: spaceBefore,
            spaceAfter: spaceAfter
        };
    }
};


Bdf.Ficheblock.wrapSelection = function (codeMirror, start, end) {
     if (Bdf.Ficheblock.checkSelection(codeMirror)) {
        let selection = codeMirror.getSelection();
        codeMirror.replaceSelection(start + selection + end, "around");
     }
     codeMirror.focus();
};
