import Component from '@ember/component';
import Key from 'mobiledoc-kit/utils/key';
import layout from '../templates/components/koenig-caption-input';
import {computed} from '@ember/object';
import {kgStyle} from 'ember-cli-ghost-spirit/helpers/kg-style';
import {run} from '@ember/runloop';

export default Component.extend({
    tagName: 'figcaption',
    classNameBindings: ['figCaptionClass'],
    layout,

    caption: '',
    captureInput: false,
    placeholder: '',

    _keypressHandler: null,
    _keydownHandler: null,

    update() {},
    addParagraphAfterCard() {},
    moveCursorToNextSection() {},
    moveCursorToPrevSection() {},

    figCaptionClass: computed(function () {
        return `${kgStyle(['figcaption'])} w-100 relative`;
    }),

    didReceiveAttrs() {
        this._super(...arguments);

        if (this.captureInput && !this._keypressHandler) {
            this._attachHandlers();
        }

        if (!this.captureInput && this._keypressHandler) {
            this._detachHandlers();
        }
    },

    willDestroyElement() {
        this._super(...arguments);
        this._detachHandlers();
    },

    actions: {
        registerEditor(editor) {
            let commands = {
                ENTER: run.bind(this, this._enter),
                ESC: run.bind(this, this._escape),
                UP: run.bind(this, this._upOrLeft),
                LEFT: run.bind(this, this._upOrLeft),
                DOWN: run.bind(this, this._rightOrDown),
                RIGHT: run.bind(this, this._rightOrDown)
            };

            Object.keys(commands).forEach((str) => {
                editor.registerKeyCommand({
                    str,
                    run() {
                        return commands[str](editor, str);
                    }
                });
            });

            this.editor = editor;
        },

        handleEnter() {
            this.addParagraphAfterCard();
        }
    },

    _attachHandlers() {
        if (!this._keypressHandler) {
            this._keypressHandler = run.bind(this, this._handleKeypress);
            window.addEventListener('keypress', this._keypressHandler);
        }
    },

    _detachHandlers() {
        window.removeEventListener('keypress', this._keypressHandler);
        this._keypressHandler = null;
        this._keydownHandler = null;
    },

    // only fires if the card is selected, moves focus to the caption input so
    // that it's possible to start typing without explicitly focusing the input
    _handleKeypress(event) {
        let key = new Key(event);
        let {editor} = this;

        if (event.target.matches('[data-kg="editor"]') && editor && !editor._hasFocus() && key.isPrintableKey() && !key.isEnter()) {
            editor.focus();
            editor.run((postEditor) => {
                postEditor.insertText(editor.post.tailPosition(), key.toString());
            });

            event.preventDefault();
        }
    },

    /* key commands ----------------------------------------------------------*/

    _enter() {
        this.send('handleEnter');
    },

    _escape(editor) {
        editor.element.blur();
    },

    _upOrLeft(editor, key) {
        let {isCollapsed, head} = editor.range;

        if (isCollapsed && head.isEqual(head.section.headPosition())) {
            return this.moveCursorToPrevSection();
        }

        // we're simulating a text input so up/down move the cursor to the
        // beginning/end of the input
        if (isCollapsed && key === 'UP') {
            return editor.selectRange(head.section.headPosition().toRange());
        }

        return false;
    },

    _rightOrDown(editor, key) {
        let {isCollapsed, tail} = editor.range;

        if (isCollapsed && tail.isEqual(tail.section.tailPosition())) {
            return this.moveCursorToNextSection();
        }

        // we're simulating a text input so up/down move the cursor to the
        // beginning/end of the input
        if (isCollapsed && key === 'DOWN') {
            return editor.selectRange(tail.section.tailPosition().toRange());
        }

        return false;
    }
});
