CKEDITOR.dialog.add('pbckcodeDialog', function (editor) {
    "use strict";

    var tab_sizes = ["1", "2", "4", "8"];

    // CKEditor variables
    var dialog;
    var shighlighter = new PBSyntaxHighlighter(editor.settings.highlighter);

    // ACE variables
    var aceEditor, aceSession, whitespace;

    // EDITOR panel
    var editorPanel = {
        id       : 'editor',
        label    : editor.lang.pbckcode.editor,
        elements : [
            {
                type     : 'hbox',
                children : [
                    {
                        type      : 'select',
                        id        : 'code-select',
                        className : 'cke_pbckcode_form',
                        label     : editor.lang.pbckcode.mode,
                        items     : editor.settings.modes,
                        'default' : editor.settings.modes[0][1],
                        setup     : function (element) {
                            if (element) {
                                element = element.getAscendant('pre', true);
                                this.setValue(element.getAttribute("data-pbcklang"));
                            }
                        },
                        commit    : function (element) {
                            if (element) {
                                element = element.getAscendant('pre', true);
                                element.setAttribute("data-pbcklang", this.getValue());
                            }
                        },
                        onChange  : function () {
                            aceSession.setMode("ace/mode/" + this.getValue());
                        }
                    },
                    {
                        type      : 'select',
                        id        : 'code-tabsize-select',
                        className : 'cke_pbckcode_form',
                        label     : 'Tab size',
                        items     : tab_sizes,
                        'default' : tab_sizes[2],
                        setup     : function (element) {
                            if (element) {
                                element = element.getAscendant('pre', true);
                                this.setValue(element.getAttribute("data-pbcktabsize"));
                            }
                        },
                        commit    : function (element) {
                            if (element) {
                                element = element.getAscendant('pre', true);
                                element.setAttribute("data-pbcktabsize", this.getValue());
                            }
                        },
                        onChange  : function (element) {
                            if (element) {
                                whitespace.convertIndentation(aceSession, " ", this.getValue());
                                aceSession.setTabSize(this.getValue());
                            }
                        }
                    }
                ]
            },
            {
                type      : 'html',
                html      : '<div></div>',
                id        : 'code-textarea',
                className : 'cke_pbckcode_ace',
                style     : 'position: absolute; top: 80px; left: 10px; right: 10px; bottom: 50px;',
                setup     : function (element) {
                    // get the value of the editor
                    var code = element.getHtml();

                    // replace some regexp
                    code = code.replace(new RegExp('<br/>', 'g'), '\n')
                        .replace(new RegExp('<br>', 'g'), '\n')
                        .replace(new RegExp('&lt;', 'g'), '<')
                        .replace(new RegExp('&gt;', 'g'), '>')
                        .replace(new RegExp('&amp;', 'g'), '&')
                        .replace(new RegExp('&nbsp;', 'g'), ' ');

                    aceEditor.setValue(code);
                },
                commit    : function (element) {
                    element.setText(aceEditor.getValue());
                }
            }
        ]
    };

    // dialog code
    return {
        // Basic properties of the dialog window: title, minimum size.
        title     : editor.lang.pbckcode.title,
        minWidth  : 600,
        minHeight : 400,
        // Dialog window contents definition.
        contents  : [
            editorPanel
        ],
        onLoad    : function () {
            dialog = this;
            // we load the ACE plugin to our div
            aceEditor = ace.edit(dialog.getContentElement('editor', 'code-textarea')
                .getElement().getId());
            // save the aceEditor into the editor object for the resize event
            editor.aceEditor = aceEditor;

            // set default settings
            aceEditor.setTheme("ace/theme/" + editor.settings.theme);
            aceEditor.setHighlightActiveLine(true);

            aceSession = aceEditor.getSession();
            aceSession.setMode("ace/mode/" + editor.settings.modes[0][1]);
            aceSession.setTabSize(editor.settings.tab_size);
            aceSession.setUseSoftTabs(true);

            // load ace extensions
            whitespace = ace.require('ace/ext/whitespace');
        },
        onShow    : function () {
            // get the selection
            var selection = editor.getSelection();
            // get the entire element
            var element = selection.getStartElement();

            // looking for the pre parent tag
            if (element) {
                element = element.getAscendant('pre', true);
            }
            // if there is no pre tag, it is an addition. Therefore, it is an edition
            if (!element || element.getName() !== 'pre') {
                element = new CKEDITOR.dom.element('pre');

                if (shighlighter.getTag() !== 'pre') {
                    element.append(new CKEDITOR.dom.element('code'));
                }
                this.insertMode = true;
            }
            else {
                if (shighlighter.getTag() !== 'pre') {
                    element = element.getChild(0);
                }
                this.insertMode = false;
            }
            // get the element to fill the inputs
            this.element = element;

            // focus on the editor
            aceEditor.focus();

            // we empty the editor
            aceEditor.setValue('');

            // we fill the inputs
            if (!this.insertMode) {
                this.setupContent(this.element);
            }
        },
        // This method is invoked once a user clicks the OK button, confirming the dialog.
        onOk      : function () {
            var pre, element;
            pre = element = this.element;

            if (this.insertMode) {
                if (shighlighter.getTag() !== 'pre') {
                    element = this.element.getChild(0);
                }
            }
            else {
                pre = element.getAscendant('pre', true);
            }

            this.commitContent(element);

            // set the full class to the code tag
            shighlighter.setCls(pre.getAttribute("data-pbcklang") + " " + editor.settings.cls);

            element.setAttribute('class', shighlighter.getCls());

            // we add a new code tag into ckeditor editor
            if (this.insertMode) {
                editor.insertElement(pre);
            }
        }
    };
});

/*
 * Resize the ACE Editor
 */
CKEDITOR.dialog.on('resize', function (evt) {
    var AceEditor = evt.editor.aceEditor;
    if (AceEditor !== undefined) {
        AceEditor.resize();
    }
});

