// shortcut suggest functionality
// auto attaches to all [with-shortcuts] elements
(function() {
    let input = null, menu = null, options = [], index = -1;
    let backtrackAfterApplying = false;
    function getCaretPos(win) {
        win = win || window;
        let doc = win.document;
        let sel, range, rects, rect;
        let x = 0, y = 0;
        if (win.getSelection) { // won't work if getSelection() isn't available!
            sel = win.getSelection();
            if(sel.toString() !== '') return null; // won't work if there isa
            if (sel.rangeCount) {
                range = sel.getRangeAt(0).cloneRange();
                if (range.getClientRects) {
                    range.collapse(true);
                    let span = doc.createElement("span");
                    if (span.getClientRects) {
                        // Ensure span has dimensions and position by
                        // adding a zero-width space character
                        span.appendChild( doc.createTextNode("\u200bXX") );
                        range.insertNode(span);
                        rect = span.getClientRects()[0];
                        x = rect.left;
                        y = rect.top;
                        let spanParent = span.parentNode;
                        spanParent.removeChild(span);

                        // Glue any broken text nodes back together
                        spanParent.normalize();

                        return [x, y];
                    }
                    return null
                }
            }
        }
        return { x: x, y: y };
    }
    function show(_input) {
        let pos = getCaretPos();
        if(pos) {
            index = -1;
            let rawOptions = $(_input).closest('[data-shortcuts]').attr('data-shortcuts');
            options = [];
            rawOptions = rawOptions.split('^^^');
            for (let i = 0; i < rawOptions.length; i++) {
                let parts = rawOptions[i].split('|||');
                options.push({
                    name: parts[0],
                    value: parts[1]
                });
            }
            menu.empty();
            for(let i = 0; i < options.length; i++) {
                menu.append(
                    $('<div/>')
                        .addClass('sc')
                        .text(options[i].name)
                        .attr('title', options[i].value)
                );
            }
            menu
                .css({
                    left: pos[0] + 'px',
                    top: (pos[1] + $(window).scrollTop()) + 'px',
                })
                .show();

        }
    }
    function discard() {
        if($('.stag-shortcuts:visible').length) {
            $('.stag-shortcuts').hide();
            return false;
        }
    }
    function highlightOption() {
        menu.find('.sc').removeClass('active');
        if(options && options.length && index >= 0 && index < options.length) {
            menu.find('.sc:eq(' + index + ')').addClass('active');
        }
    }
    function apply() {
        if(input && options && options.length && index >= 0 && index < options.length) {
            // $(input).focus();
            if(backtrackAfterApplying) {
                document.execCommand("delete", true, null);
            }
            document.execCommand("insertText", true, options[index].value);
            discard();
        }
    }
    function isVisible() {
        return !!$('.stag-shortcuts:visible').length;
    }
    function init() {

        var selectedText = '';

        $('.stag-shortcuts').remove();
        options = [];
        menu = $('<div/>')
            .addClass('stag-shortcuts')
            .appendTo('body');

        $(document)
            .off('mousedown.outside-shortcuts')
            .on('mousedown.outside-shortcuts', function(_e) {
                if($(_e.target).closest('.stag-shortcuts').length) return;
                return discard();
            });
        $(document)
            .off('keypress.shortcuts', '[with-shortcuts]')
            .on('keypress.shortcuts', '[with-shortcuts]', function(_e) {
                // console.log('KP: ', _e.which);
                input = this;
                switch(_e.which) {
                    case 64:
                        backtrackAfterApplying = true;
                        show(this);
                        break;
                    default:
                        if(isVisible()) return false;
                        break;
                }
            })
            .off('keydown.shortcuts', '[with-shortcuts]')
            .on('keydown.shortcuts', '[with-shortcuts]', function(_e) {
                // console.log('KD: ', _e.which);
                input = this;
                let consumed = false;
                switch(_e.which) {
                    case 32:
                        if(_e.ctrlKey && !isVisible()) {
                            backtrackAfterApplying = false;
                            show(this);
                            return false;
                        }
                        else {
                            if(!isVisible()) return;
                            _e.preventDefault();
                            apply();
                            consumed = true;
                        }
                        break;
                    case 27:
                        if(!isVisible()) return;
                        consumed = !discard();
                        break;
                    case 38:
                        if(!isVisible()) return;
                        if(index > 0) index--;
                        highlightOption();
                        consumed = true;
                        break;
                    case 40:
                        if(!isVisible()) return;
                        if(index < options.length - 1) index++;
                        highlightOption();
                        consumed = true;
                        break;
                    case 13:
                        if(!isVisible()) return;
                        apply();
                        consumed = true;
                        break;
                    default:
                        consumed = isVisible();
                        break;
                }
                if(consumed) return false;
            });
        $(document)
            .off('mousedown.apply-shortcuts', '.stag-shortcuts>.sc')
            .on('mousedown.apply-shortcuts', '.stag-shortcuts>.sc', function(_e) {
                index = $(this).index();
                apply();
                return false;
            });
        $(document)
            .off('mousedown.add-shortcuts', '.add-shortcut')
            .on('mousedown.add-shortcuts', '.add-shortcut', function(_e) {
                let hasFocus = $(document.activeElement).closest('.note-content, .rte-holder').length;
                if(hasFocus) {
                    selectedText = window.getSelection().toString();
                    if(selectedText !== '') return;
                }
                return false;
            })
            .off('click.add-shortcuts', '.add-shortcut')
            .on('click.add-shortcuts', '.add-shortcut', function(_e) {
                // if(selectedText === '') return;
                $('#selected-sc-text').val(selectedText);
                $('#create-shortcut-form')
                    .attr('data-editor-id', $(this).attr('data-editor-id'))
                    .css({
                        left: $(this).offset().left + 'px',
                        top: ($(this).offset().top + $(this).outerHeight()) + 'px'
                    })
                    .show();
                showMoeFormMask();
                return false;
            })
            .off('submit.add-shortcut', '#create-shortcut-form')
            .on('submit.add-shortcut', '#create-shortcut-form', function(_e) {
                if(!input) input = $('.note-content [contenteditable][data-editor-id="' + $(this).attr('data-editor-id') + '"]').first();
                if(!input) return false;
                var label = $(this).find('[name="shortcut"]').val(),
                    content = $(this).find('[name="text"]').val();
                if(!this.checkValidity()) return false;
                $.post('/api/proTextShortcut/create', $(this).serialize(), function(_data) {
                    if(_data && _data.success && input) {
                        var options = [$(input).closest('[data-shortcuts]').attr('data-shortcuts')]
                        options.push(label + '|||' + content);
                        options = options.join('^^^');
                        $(input).closest('[data-shortcuts]').attr('data-shortcuts', options);
                        toastr.success('Shortcut saved');
                        hideMoeFormMask();
                        $('#create-shortcut-form').hide();
                        $(input).focus();
                    }
                }, 'json');
                return false;
            })
            .off('reset.add-shortcut', '#create-shortcut-form')
            .on('reset.add-shortcut', '#create-shortcut-form', function(_e) {
                if(!input) input = $('.note-content [contenteditable][data-editor-id="' + $(this).attr('data-editor-id') + '"]').first();
                if(!input) return false;
                hideMoeFormMask();
                $('#create-shortcut-form').hide();
                $(input).focus();
            });

    }
    addMCInitializer('shortcut-suggest', init);
})();


