/* --------------------------------------------------------------
 editor_instances.js 2016-09-09
 Gambio GmbH
 http://www.gambio.de
 Copyright (c) 2016 Gambio GmbH
 Released under the GNU General Public License (Version 2)
 [http://www.gnu.org/licenses/gpl-2.0.html]
 --------------------------------------------------------------
 */

jse.libs.editor_instances = jse.libs.editor_instances || {};

/**
 * ## Editor Instances Library
 *
 * This library provides a common API for editor widget instances manipulation.
 *
 * @module Admin/Libs/editor_instances
 * @exports jse.libs.editor_instances
 */
(function (exports) {

    'use strict';

    /**
     * Editor construct methods
     *
     * @type {Object}
     */
    const constructors = {
        ckeditor($textarea) {
            const tags = [
                'p',
                'div',
                'script',
                'style',
                'form'
            ];

            const formattingRules = {
                indent: true,
                breakBeforeOpen: true,
                breakAfterOpen: true,
                breakBeforeClose: true,
                breakAfterClose: true
            };

            const config = {
                filebrowserBrowseUrl: 'includes/ckeditor/filemanager/index.html',
                baseHref: jse.core.config.get('appUrl') + '/admin',
                enterMode: CKEDITOR.ENTER_BR,
                shiftEnterMode: CKEDITOR.ENTER_P,
                language: jse.core.config.get('languageCode'),
                useRelPath: true,
                on: {
                    instanceReady(event) {
                        for (let tag of tags) {
                            this.dataProcessor.writer.setRules(tag, formattingRules);
                        }
                    }
                }
            };

            const name = $textarea.attr('name');
            CKEDITOR.replace(name, config);
            return CKEDITOR.instances[name];
        },
        codemirror($textarea) {
            const config = {
                mode: 'htmlmixed',
                lineNumbers: true,
                lineWrapping: true
            };

            return CodeMirror.fromTextArea($textarea[0], config);
        }
    };

    /**
     * Editor destruct methods
     *
     * @type {Object}
     */
    const destructors = {
        ckeditor($textarea) {
            const name = $textarea.attr('name');
            CKEDITOR.instances[name].destroy();
        },
        codemirror($textarea) {
            const instance = $textarea.siblings('.CodeMirror')[0].CodeMirror;
            instance.toTextArea();
        }
    };

    /**
     * Editor instance methods
     *
     * @type {Object}
     */
    const getInstance = {
        ckeditor($textarea) {
            return CKEDITOR.instances[$textarea.attr('name')];
        },
        codemirror($textarea) {
            return $textarea.siblings('.CodeMirror')[0].CodeMirror;
        }
    };

    /**
     * Create new editor instance.
     *
     * @param {jQuery} $textarea Textarea selector to be modified.
     * @param {String} type Provide a type that is supported by the widget.
     *
     * @return {CKEditor|CodeMirror} Returns the create editor instance.
     */
    exports.create = function ($textarea, type) {
        if (constructors[type] === undefined) {
            throw new Error('Provided editor type is not supported: ' + type);
        }

        const instance = constructors[type]($textarea);
        instance.type = type;

        return instance;
    };

    /**
     * Switch to a new editor type.
     *
     * @param {jQuery} $textarea Textarea selector to be modified.
     * @param {String} currentType Provide the current editor type.
     * @param {String} newType Provide the new editor type.
     *
     * @return {CKEditor|CodeMirror} Returns the new editor instance.
     */
    exports.switch = function ($textarea, currentType, newType) {
        if (destructors[currentType] === undefined) {
            throw new Error('Provided editor type is not supported: ' + currentType);
        }

        destructors[currentType]($textarea);

        return exports.create($textarea, newType);
    };

    /**
     * Destroy an existing editor instance.
     *
     * @param {jQuery} $textarea Textarea selector to be destroyed.
     * @param {String} customInitEventType Optional (''), if the editor was initialized with a custom init-event-type,
     * then this must be unbound by editor destroy.
     */
    exports.destroy = function ($textarea, customInitEventType = '') {
        if (customInitEventType && customInitEventType !== 'JSENGINE_INIT_FINISHED') {
            $(window).off(customInitEventType);
        }

        const type = $textarea.data('editorType');

        if (destructors[type] === undefined) {
            throw new Error('Provided editor type is not supported: ' + type);
        }

        destructors[type]($textarea);
    };

    /**
     * Get an editor instance.
     *
     * @param {jQuery} $textarea Textarea selector from which the instance will be retrieved.
     *
     * @return {CKEditor|CodeMirror} Returns the corresponding editor instance.
     */
    exports.getInstance = function ($textarea) {
        const type = $textarea.data('editorType');

        if (destructors[type] === undefined) {
            throw new Error('Provided editor type is not supported: ' + type);
        }

        return getInstance[type]($textarea);
    };

})(jse.libs.editor_instances);