/* <copyright>
This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
(c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
</copyright> */

////////////////////////////////////////////////////////////////////////
//
var Montage = 		require("montage/core/core").Montage,
    Component = 	require("montage/ui/component").Component;

exports.CodeEditorController = Montage.create(Component, {
    hasTemplate: {
        value: false
    },

    _currentDocument: {
        value : null
    },

    currentDocument : {
        get : function() {
            return this._currentDocument;
        },
        set : function(value) {
            if (value === this._currentDocument) {
                return;
            }

            this._currentDocument = value;

            if(!value) {

            } else if(this._currentDocument.currentView === "code") {
                this.autocomplete = !this.codeCompletionSupport[this._currentDocument.model.file.extension];
                this._currentDocument.model.views.code.editor.focus();
                this.applySettings();
            }
        }
    },

    _codeEditor : {
        value:null
    },

    codeEditor:{
        get: function(){return this._codeEditor;},
        set: function(value){this._codeEditor = value;}
    },

    codeCompletionSupport : {
        value: {"js": true}
    },

    autocomplete: {
        value: false
    },

    _automaticCodeComplete: {
        value:false
    },

    automaticCodeComplete:{
        get: function(){
            return this._automaticCodeComplete;
        },
        set: function(value) {
            if(this._automaticCodeComplete !== value) {
                this._automaticCodeComplete = value;
            }
        }
    },

    _editorTheme: {
        value:"default"
    },

    editorTheme:{
        get: function(){
            return this._editorTheme;
        },
        set: function(value){
            this._editorTheme = value;
        }
    },

    _zoomFactor: {
        value:100
    },

    zoomFactor:{
        get: function() {
            return this._zoomFactor;
        },
        set: function(value) {
            this.handleZoom(value);
        }
    },

    deserializedFromTemplate: {
        value: function() {
            //TODO:add logic to check some configuration file to load the right code editor
            this.codeEditor = CodeMirror;
        }
    },

    /**
     * Public method
     * Creates an editor instance
     */
    createEditor : {
        value:function(codeDocumentView, type, documentType, textDocument){
            var self = this, editorOptions = null;

            editorOptions = {
                               lineNumbers: true,
                               matchBrackets:true,
                               mode: type,
                               onChange: function(){
                                   var historySize = codeDocumentView.editor.historySize();
                                   if(historySize.undo>0){
                                       textDocument.model.needsSave = true;
                                   }else if(historySize.undo===0 && historySize.redo>0){
                                       textDocument.model.needsSave = false;
                                   }
                               },
                               onCursorActivity: function() {
                                   codeDocumentView.editor.matchHighlight("CodeMirror-matchhighlight");
                                   codeDocumentView.editor.setLineClass(codeDocumentView.editor.hline, null, null);
                                   codeDocumentView.editor.hline = codeDocumentView.editor.setLineClass(codeDocumentView.editor.getCursor().line, null, "activeline");
                               }
                           };

            //configure auto code completion if it is supported for that document type
            if(this.autocomplete) {

                editorOptions.onKeyEvent = function(cm, keyEvent){
                    self._codeCompletionKeyEventHandler.call(self, cm, keyEvent, documentType)
                };

            }

            return self.codeEditor.fromTextArea(codeDocumentView.textArea, editorOptions);
        }
    },

    /**
     * Private method
     * key event handler for showing code completion dropdown
     */
    _codeCompletionKeyEventHandler:{
        enumerable:false,
        value: function(cm, keyEvent, documentType) {
            //comment shortkeys
            if((keyEvent.metaKey || keyEvent.ctrlKey) && !keyEvent.shiftKey && keyEvent.keyCode === 191){//ctrl+/
                this.commentSelection(true);
                return;
            }
            //uncomment shortkeys
            if((keyEvent.metaKey || keyEvent.ctrlKey) && keyEvent.shiftKey && keyEvent.keyCode === 191){//ctrl+shift+/
                this.commentSelection(false);
                return;
            }

            //===manually triggered code completion
            if((this.automaticCodeComplete === false)){
                if(keyEvent.ctrlKey && keyEvent.keyCode === 32){//Ctrl+Space
                    this.codeEditor.simpleHint(cm, this.codeEditor.javascriptHint);
                }
            }
            //===automatic auto complete [performance is slower]
            else if(this._showAutoComplete(documentType, keyEvent)){
                this.codeEditor.simpleHint(cm, this.codeEditor.javascriptHint);
            }
       }
    },

    /**
     * Private method
     * checks for valid keyset to show code completion dropdown
     */
    _showAutoComplete : {
        enumerable:false,
        value:function(documentType, keyEvent){
            var status=false;

            if((keyEvent.metaKey || keyEvent.ctrlKey) &&  (keyEvent.keyCode === 83)){//ctrl+s
                return false;
            }

            switch(documentType){
                case "js":
                    if((keyEvent.type === "keyup")//need seperate keycode set per mode
                        && ((keyEvent.keyCode > 47 && keyEvent.keyCode < 57)//numbers
                            || (keyEvent.keyCode > 64 && keyEvent.keyCode <91)//letters
                            || (keyEvent.keyCode === 190)//period
                            || (keyEvent.keyCode === 189)//underscore, dash
                           )
                        && !(keyEvent.ctrlKey //ctrl
                            || keyEvent.metaKey//cmd
                            || (keyEvent.keyCode === 219)//open bracket [
                            || (keyEvent.keyCode === 221)//close bracket ]
                            || (keyEvent.shiftKey && keyEvent.keyCode === 219)//open bracket {
                            || (keyEvent.shiftKey && keyEvent.keyCode === 221)//close bracket }
                            || (keyEvent.shiftKey && keyEvent.keyCode === 57)//open bracket (
                            || (keyEvent.shiftKey && keyEvent.keyCode === 48)//close bracket )
                           )
                    ){
                        status = true;
                        break;
                    }
                default :
                    status = false;
            }

            return status;
        }
    },

    getSelectedRange:{
        value:function(editor){
            return { from: editor.getCursor(true), to: editor.getCursor(false) };
        }
    },

    commentSelection:{
        value: function(isComment){
            var range = this.getSelectedRange(this.currentDocument.model.views.code.editor);
            this.currentDocument.model.views.code.editor.commentRange(isComment, range.from, range.to);
        }
    },

    handleThemeSelection:{
        value: function(){
            this.currentDocument.model.views.code.editor.setOption("theme", this.editorTheme);
            this.currentDocument.model.views.code.applyTheme("cm-s-"+this.editorTheme);
        }
    },

    handleZoom:{
        value:function(value){
            var originalFont=13,originalLineHeight=16;
            this._zoomFactor = value;
            this.currentDocument.model.views.code.textViewContainer.style.fontSize = ""+((value/100)*originalFont)+"px";
            this.currentDocument.model.views.code.textViewContainer.style.cursor = "text";
            this.currentDocument.model.views.code.textViewContainer.querySelector(".CodeMirror").style.lineHeight = ""+((value/100)*originalLineHeight)+"px";
            this.currentDocument.model.views.code.editor.refresh();//refresh editor display for xoom
        }
    },

    applySettings:{
        value:function(){
            //set theme
            this.handleThemeSelection();
            //set zoom
            this.handleZoom(this._zoomFactor);
        }
    }
});