/* global Bdf,Ficheform,CodeMirror,Infinity,$$ */

Ficheform.Section = {};

Ficheform.Section.ficheElement = null;

Ficheform.Section.codeMirrorUnitMap = new Map();

Ficheform.Section.init = function () {
    $$({ficheformEntry: "section"}).each(function (index, element) {
        Ficheform.Section.initSection(element);
    });
};

Ficheform.Section.initSection = function (element) {
    var entryKey = element.dataset.ficheformKey;
    var sectionId = Bdf.generateId();
    var $entry = $(element);
    var corpus = Ficheform.getCurrentCorpus(element);
    var factorStorageKey =  entryKey + ".factor";
    var textArea = $$.one($entry, {ficheformRole: "sectiontext"});
    var codeMirrorUnit;
    $$($entry, {ficheformRole: "section-area"}).prepend((Bdf.render("ficheform:section/areatoolbar", {
        sectionId: sectionId,
        noTab: Ficheform.getOption("noTab")
    }))).prepend(Bdf.render("ficheform:section/codemirrortoolbar", {
        sectionId: sectionId,
        noTab: Ficheform.getOption("noTab")
    }));
    $$(sectionId, "syntaxswitch").change(function () {
        _switchCodeMirror(this.checked);
    });
    $$(sectionId, "increase").click(_increaseArea);
    $$(sectionId, "decrease").click(_decreaseArea);
    $$(sectionId, "zoomedit").click(_zoomEdit);
    _checkLocalStore();
    if (_isSyntaxActive()) {
        $$(sectionId, "syntaxswitch").prop("checked", true).trigger('change');
    }

    
    function _checkLocalStore() {
        var localStore = Bdf.getMainLocalStorage();
        if (!localStore) {
            return;
        }
        if (localStore.hasOwnProperty(factorStorageKey)) {
            let rows = textArea.rows;
            let factor =  localStore[factorStorageKey];
            if (factor > 0) {
                for(let j = 1; j <= factor; j++) {
                    rows = rows * 2;
                }
            } else if (factor < 0) {
                factor = -factor;
                for(let j = 1; j <= factor; j++) {
                    rows = rows / 2;
                }
            }
            textArea.rows = rows;
        }
    }
    
    function _isSyntaxActive() {
        if (textArea.dataset.userSyntax) {
            switch(textArea.dataset.userSyntax) {
                case "active":
                    return true;
                case "inactive":
                    return false;
            }
        }
        return Ficheform.ARGS.syntaxActive;
    }
    
    function _switchCodeMirror(checked) {
        if (!checked) {
            $$(sectionId, "codemirrortoolbar").removeClass("ficheform-section-Active");
            if (codeMirrorUnit) {
                codeMirrorUnit.codeMirror.toTextArea();
                codeMirrorUnit.$ficheblockButtons.empty();
                codeMirrorUnit = null;
                $$(sectionId, "areatoolbar").show();
                Ficheform.Section.codeMirrorUnitMap.set(entryKey, null);
                _storeSyntax(false);
            }
        } else {
            $$(sectionId, "areatoolbar").hide();
            $$(sectionId, "codemirrortoolbar").addClass("ficheform-section-Active");
            codeMirrorUnit = Ficheform.Section.initSectionCodeMirror($entry, textArea, true, corpus);
            codeMirrorUnit.codeMirror.on('change', Ficheform.signalChange);
            Ficheform.Section.codeMirrorUnitMap.set(entryKey, codeMirrorUnit);
            _storeSyntax(true);
        }
    }
    
    function _increaseArea() {
        let rows = textArea.rows;
        textArea.rows = rows * 2;
        _storeFactor(true);
    }

    function _decreaseArea() {
        let rows = textArea.rows;
        if (rows < 6) {
            return;
        }
        rows = rows / 2;
        textArea.rows = rows;
        _storeFactor(false);
    }
    
    function _zoomEdit() {
        let url = "edition?page=zoomedit&appelant=" + textArea.id + "&corpus=" + corpus;
        Ficheform.openDialog(url,"fenetre_"+ entryKey,670,570);
    }
    
    function _storeSyntax(isSyntax) {
        let key = textArea.dataset.userKey + "_syntax";
        let value = (isSyntax)? "1": "0";
        Bdf.Ajax.storeUserPref("ficheform_corpus_" + corpus, key, value);
    }
    
    function _storeFactor(increase) {
        var localStore = Bdf.getMainLocalStorage();
        if (!localStore) {
            return;
        }
        let currentValue, newValue;
        if (localStore.hasOwnProperty(factorStorageKey)) {
            currentValue = localStore[factorStorageKey];
        } else {
            currentValue = 0;
        }
        if (increase) {
           newValue = currentValue + 1;
        } else {
            newValue = currentValue -1;
        }
        localStore[factorStorageKey] = newValue;
        Bdf.putMainLocalStorage(localStore);
    }
};

Ficheform.Section.initSectionCodeMirror = function (container, textArea, disableOnBlur, corpus) {
    var genId = Bdf.generateId();
    var $ficheblockButtons = $$(container, {role: "ficheform-ficheblockbuttons"});
    var spellcheckAvailable = _isSpellcheckAvailable();
    var spellcheckActive = _isSpellcheckActive();
    var previewActive = false;
    var codeMirror = Bdf.toCodeMirror(textArea, {
        mode: 'ficheblock',
        theme: 'bdf',
        lineWrapping: true,
        viewportMargin: Infinity,
        inputStyle: "contenteditable",
        spellcheck: spellcheckActive,
        extraKeys: {
            "F1": function () {
                if (previewActive) {
                    return CodeMirror.Pass;
                } else {
                    _showPreview();
                }
            },
            "Tab": false,
            "Shift-Tab": false
        }
    });
    var codeMirrorUnit = new Ficheform.Section.CodeMirrorUnit(textArea, codeMirror, $ficheblockButtons);
    var disableTimeout = false;
    $ficheblockButtons.html(Bdf.render("ficheform:section/ficheblockbuttons", {
        genId: genId,
        spellcheckAvailable: spellcheckAvailable,
        spellcheckActive: spellcheckActive
    }));
    _initSpellcheck();
    codeMirror.on('renderLine', function (cm, line, element) {
        if (spellcheckActive) {
            for (let i = 0, len = element.children.length; i < len; i++) {
                _testSpellcheck(element.children[i]);
            }
        }
    });
    codeMirror.on('cursorActivity', _checkToolbar);
    codeMirror.on('focus', _checkToolbar);
    if (disableOnBlur) {
        codeMirror.on('blur', _disableToolbar);
    }
    _init("undo", function () {
        codeMirror.getDoc().undo();
        codeMirror.focus();
        _checkToolbar();
    });
    _init("redo", function () {
        codeMirror.getDoc().redo();
        codeMirror.focus();
        _checkToolbar();
    });
    _init("bold", function () {
        Bdf.Ficheblock.wrapSelection(codeMirror, "{{", "}}");
    });
    _init("italic", function () {
        Bdf.Ficheblock.wrapSelection(codeMirror, "{", "}");
    });
    _init("bolditalic", function () {
        Bdf.Ficheblock.wrapSelection(codeMirror, "{{{", "}}}");
    });
    _init("urlref", function () {
        Ficheform.Section.Overlay.showUrlForm(codeMirror);
    });
    _init("footnote", function () {
        Ficheform.Section.Overlay.showFootnoteForm(codeMirror);
    });
    _init("ficheref", function () {
        Ficheform.Section.Overlay.showFicheForm(codeMirror);
    });
    _init("stylechoice", function () {
        Ficheform.Section.Overlay.showStyleForm(codeMirror);
    });
    _init("heading1", function () {
        Bdf.Ficheblock.insertCharsAtStart(codeMirror, "#");
    });
    _init("heading2", function () {
        Bdf.Ficheblock.insertCharsAtStart(codeMirror, "##");
    });
    _init("heading3", function () {
        Bdf.Ficheblock.insertCharsAtStart(codeMirror, "###");
    });
    _init("ul", function () {
        Bdf.Ficheblock.insertList(codeMirror);
    });
    _init("zonechoice", function () {
        Ficheform.Section.Overlay.showZoneForm(codeMirror);
    });
    _init("paste", function () {
        Ficheform.Section.Overlay.showPasteAndConvert(codeMirror);
    });
    _init("spellcheck", function () {
        let currentState = this.dataset["state"];
        let newState;
        if (currentState === "on") {
            this.classList.remove("global-button-On");
            newState = "off";
            spellcheckActive = false;
        } else {
            this.classList.add("global-button-On");
            newState = "on";
            spellcheckActive = true;
        }
        this.dataset["state"] = newState;
        codeMirror.setOption("spellcheck", spellcheckActive);
        codeMirror.focus();
        _initSpellcheck();
        _storeSpellcheckState(newState);
    });
    _init("preview", function () {
        _showPreview();
    });
    return codeMirrorUnit;

    
    function _init(key, click) {
        return $$(genId, key).focus(_stopDisable).click(click);
    }
    
    function _checkToolbar() {
        var newEnabled = Bdf.Ficheblock.checkEnabled(codeMirror);
        for(let prop in newEnabled) {
            $$($ficheblockButtons, {_element: "button", enableType: prop}).prop("disabled", !newEnabled[prop]);
        }
    };
    
    function  _disableToolbar() {
         if (!disableTimeout) {
            disableTimeout = setTimeout(function() {
                $$($ficheblockButtons, {_element: "button"}).prop("disabled", true);
                disableTimeout = false;
            }, 10);
        }
    }
    
    function _stopDisable() {
        if (disableTimeout) {
            clearTimeout(disableTimeout);
            disableTimeout = false;
        }
    }
    
    function _isSpellcheckAvailable() {
       let spellchekAttribute = textArea.getAttribute("spellcheck");
       if ((spellchekAttribute) && (spellchekAttribute === "false")) {
           return false;
       } else {
           return true;
       }
    }
    
    function _initSpellcheck() {
        if (spellcheckActive) {
            _testSpellcheck(codeMirror.getWrapperElement());
        }
    }
    
    function _testSpellcheck(element) {
        if (__containsNoSpellcheckClass()) {
            element.setAttribute("spellcheck", "false");
        } else {
            for (let i = 0, len = element.children.length; i < len; i++) {
                _testSpellcheck(element.children[i]);
            }
        }
        
        function __containsNoSpellcheckClass() {
            for(let i = 0, len = element.classList.length; i < len; i++) {
                switch(element.classList[i]) {
                    case "cm-ficheblock-attname":
                    case "cm-ficheblock-attvalue":
                    case "cm-ficheblock-zone-parameters":
                    case "cm-ficheblock-codecontent":
                    case "cm-ficheblock-span-tech":
                    case "cm-ficheblock-ref":
                    case "cm-error":
                    case "cm-string":
                        return true;
                }
            }
            return false;
        }
    }
    
    function _storeSpellcheckState(state) {
        let key = textArea.dataset.userKey + "_spellcheck";
        let value = (state === "on")? "1": "0";
        Bdf.Ajax.storeUserPref("ficheform_corpus_" + corpus, key, value);
    }
    
    function _isSpellcheckActive() {
        if (!spellcheckAvailable) {
            return false;
        }
        if (textArea.dataset.userSpellcheck) {
            switch(textArea.dataset.userSpellcheck) {
                case "active":
                    return true;
                case "inactive":
                    return false;
            }
        }
        return true;
    }
    
    function _showPreview() {
        previewActive = true;
        Ficheform.Section.Overlay.showSectionPreview(codeMirror, corpus, function () {
            previewActive = false;
        });
    }

};

Ficheform.Section.getUriLinkedToFicheArray = function (role) {
    var resultArray = new Array();
    var $uris;
    if (Ficheform.Section.ficheElement) {
        $uris = $$(Ficheform.Section.ficheElement, {ficheformRole: role});
    } else {
        $uris = $$({ficheformRole: role});
    }
    for(let i = 0, len = $uris.length; i < len; i++) {
        let uri = $($uris[i]).text();
        if (uri.indexOf('/') > -1) {
            if ($.inArray(uri, resultArray) === -1) {
               	resultArray.push(uri);
            }
        }
    }
    return resultArray;
};

Ficheform.Section.getMatchingLineRange = function (textArea, position) {
    var lineNumber = Ficheform.Section.getMatchingLine(textArea, position);
    var array = textArea.value.split('\n');
    if (array.length < lineNumber) {
        return false;
    }
    var start = 0;
    for(let i = 0; i < (lineNumber -1); i++) {
        start = start + array[i].length + 1;
    }
    var end = start + array[lineNumber -1].length;
    return [start, end];
};

Ficheform.Section.getMatchingLine = function (element, position) {
    if (element.dataset.matchingLines) {
        try {
            let array = JSON.parse(element.dataset.matchingLines);
            if (Array.isArray(array)) {
                let length = array.length / 2;
                for(let i = 0; i < length; i++) {
                    let j = 2 * i;
                    if (array[j] == position) {
                        return array[j+1];
                    }
                }
            }
        } catch(error) {
        }
    }
    return 1;
};


Ficheform.Section.CodeMirrorUnit = function (textArea, codeMirror, $ficheblockButtons) {
    this.textArea = textArea;
    this.codeMirror = codeMirror;
    this.$ficheblockButtons = $ficheblockButtons;
};

Ficheform.Section.CodeMirrorUnit.prototype.focusOnFicheBlock = function (position) {
    var codeMirror = this.codeMirror;
    var lineIndex = Ficheform.Section.getMatchingLine(this.textArea, position) - 1;
    var start = {
        line: lineIndex,
        ch: 0
    };
    setTimeout(function () {
        codeMirror.focus();
        codeMirror.setCursor(start);
        codeMirror.setSelection(start, {line: lineIndex, ch: null});
        codeMirror.scrollIntoView({line: lineIndex + 5, ch: 0});
    }, 100);
        
};
