/// class PD.Manage.Modules.CodeEditor
/// using PD.Manage.Module

PD.Manage.Modules.CodeEditor = PD.Web.UI.Controls.Control.extend({

    //===================================
    // FIELDS
    //===================================

    _editor: null,
    _hasChanges: false,

    //===================================
    // PROPERTIES
    //===================================

    get_editor: function () {
        return this._editor;
    },

    get_renderer: function () {
        return this.get_editor().renderer;
    },

    get_hasChanges: function () {
        return this._hasChanges;
    },

    set_hasChanges: function (value) {
        this._hasChanges = value;
    },

    //===================================
    // EVENT HANDLERS
    //===================================

    onChange: function () {

        var fn = this.get_options().change;

        if (!this.get_hasChanges() && PD.Type.isFunction(fn)) {
            this.set_hasChanges(true);
            fn(this);
        }

    },

    onSave: function () {

        var fn = this.get_options().save;

        if (PD.Type.isFunction(fn)) {
            this.set_hasChanges(false);
            fn(this);
        }

    },

    onActivate: function (e) {
        ace.config.set("basePath", PD.Path.resolve("~/scripts/pdjs/external/ace"));
        this._editor = ace.edit(this.get_node()[0]);
        this.get_editor().getSession().on("change", $.proxy(this.onChange, this));
        this.get_editor().renderer.setShowPrintMargin(false);
        this.get_editor().setShowFoldWidgets(true);
        this.get_editor().getSession().setUseSoftTabs(false);
    },

    //===================================
    // PUBLIC METHODS
    //===================================

    showInvisibles: function (value) {
        if (value != null) {
            this.get_editor().setShowInvisibles(value);
        }
        return this.get_editor().getShowInvisibles();
    },

    showIndents: function (value) {
        if (value != null) {
            this.get_editor().setDisplayIndentGuides(value);
        }
        return this.get_editor().getDisplayIndentGuides();
    },

    showLineNumbers: function (value) {
        if (value != null) {
            this.get_renderer().setShowGutter(value);
        }
        return this.get_renderer().getShowGutter();
    },

    fontSize: function (value) {
        if (value != null) {
            this.get_editor().setFontSize(value);
        }
        return this.get_editor().getFontSize();
    },

    content: function (value) {

        var result = this.get_editor().getValue();

        if (value != null) {
            this.get_editor().setValue(value);
            this.get_editor().clearSelection();
            this.get_editor().moveCursorTo(0, 0);
        }

        return result;

    },

    focus: function () {
        this.get_editor().focus();
        //this.get_editor().gotoLine(1);
    },

    save: function () {
        this.onSave();
    },

    setStyle: function (mimeType) {

        var mode = this._getStyleMode(mimeType),
            theme = this._getStyleTheme(mimeType);

        this.get_editor().setTheme(theme);
        this.get_editor().session.setMode({ path: mode, v: Date.now() });

    },

    addMarker: function (message, startOnLine, endOnLine) {

        var Range = ace.require('ace/range').Range;

        endOnLine = endOnLine || startOnLine;

        this.get_editor().session.addMarker(new Range(startOnLine, 0, endOnLine, 1), "-pd-ace-editor-line-highlight", "fullLine");
        this.get_editor().focus();
        this.get_editor().gotoLine(startOnLine + 1);

        this._editor.session.setAnnotations([{
            row: startOnLine,
            column: 0,
            text: message || "Unknown error.",
            type: "error"
        }]);

    },

    clearMarkers: function () {

        var session = this.get_editor().session,
            markers = session.getMarkers();

        _.each(markers, function (marker) {
            session.removeMarker(marker.id);
        });

    },

    //===================================
    // PROTECTED METHODS
    //===================================

    template: function (e) {
        return "<div style='position:absolute;top:0;left:0;right:0;bottom:0;overflow:auto;padding:10px;background-color:#FFFFFF;'></div>";
    },

    //===================================
    // PRIVATE METHODS
    //===================================

    _getStyleTheme: function (mimeType) {

        var result = null,
            themes = {
                "text/html": "ace/theme/chrome",
                "text/javascript": "ace/theme/chrome",
                "text/plain": "ace/theme/chrome",
                "text/css": "ace/theme/tomorrow",
                "text/xml": "ace/theme/sqlserver",
                "text/json": "ace/theme/eclipse"
            };

        result = themes[mimeType] || themes["text/plain"];

        return result;

    },

    _getStyleMode: function (mimeType) {

        var result = null,
            modes = {
                "text/html": "ace/mode/html",
                "text/javascript": "ace/mode/javascript",
                "text/plain": "ace/mode/text",
                "text/css": "ace/mode/css",
                "text/xml": "ace/mode/xml",
                "text/json": "ace/mode/json5"
            };

        result = modes[mimeType] || modes["text/plain"];

        return result;

    }

});