/**
 * All content on this website (including text, images, source
 * code and any other original works), unless otherwise noted,
 * is licensed under a Creative Commons License.
 * 
 * http://creativecommons.org/licenses/by-nc-sa/2.5/
 * 
 * Copyright (C) 2010 Open-Xchange, Inc.
 * Mail: info@open-xchange.com 
 * 
 * @author Viktor Pracht <viktor.pracht@open-xchange.com>
 */

(function() {
    
    var activeService, activeGrid, grids;
    var folderPath = new FolderPath("messaging");
    
    register("OX_Configuration_Loaded", function() {
    	// todo: must be replaced
        //oMain--FolderTree.enabled_modules.messaging = true;
        menulastviews.messaging = "messaging";
        register("NewMessage", function() {
            if (activeService) activeService.newMessage.getMessage();
        });
        function updateMenu() {
            if (activeGrid) Editor.selected(activeGrid.selection.count);
        }
        for (var i in allServices) {
            var actions = allServices[i].actions;
            if (!actions) {
                continue;
            }
            register("OX_SELECTED_ITEMS_CHANGED", updateMenu);
            register("OX_menu_Change_Height", updateMenu);
            register("OX_Switched", updateMenu);
            var context = MenuNodes.createSmallButtonContext(i, _("Actions"),
                                                             "messaging");
            for (var j in actions) actions[j].createMenuItem(context);
            addMenuNode(context.node, MenuNodes.FIXED, 40);
            allServices[i].menuNode = context.node;
        }
    });
    
    registerView("messaging",
        function() {
            showNode("messaging");
        }, function(type) {
            if (!grids) {
            	grids = new MessagingGrids();
            	grids.selection.events.register("Selected", Editor.selected);
            }
            changeFolder(type);
        }, function() {
        	grids.disable();
            folderPath.clear();
        }, function() {
            hideNode("messaging");
        }, changeFolder);
    
    function getBody(message) {    	
        var retval = {};
        var contentType = message.contentType && message.contentType.type
                       || message.headers && message.headers["Content-Type"] &&
                          message.headers["Content-Type"].type;
                
        switch (contentType) {
            case "text/plain":
                retval.plain = message.body;
                break;
            case "text/html":
                retval.html = message.body;
                break;
            default:
                if (contentType && contentType.substring(0, 10) == "multipart/") {
                    for (var i = 0; i < message.body.length; i++) {
                        var sub = getBody(message.body[i]);
                        for (var j in sub) {
                            if (!retval[j]) retval[j] = sub[j];
                        }
                    }
                }
        }
        return retval;
    } 
    
    function getElements(div) {
        var e = {};
        if (!div.firstChild) {
            div.appendChild(e.picture = newnode("img", { flt: "left",
                width: "4em", height: "4em", margin: "0.4em" }));
            div.appendChild(newnode("div", { marginLeft: "4.8em" }, 0, [
                e.time = newnode("span", { flt: "right" }, 0, [newtext()]),
                e.from = newnode("span", { fontWeight: "bold" }, 0, [newtext()])
            ]));
            div.appendChild(e.text = newnode("div",
                { marginLeft: "4.8em", height: "3.2em",
                  whiteSpace: "normal", overflow: "hidden" }));
        } else {
            e.picture = div.firstChild;
            e.time = e.picture.nextSibling.firstChild;
            e.from = e.time.nextSibling;
            e.text = e.picture.nextSibling.nextSibling;
        }
        return e;
    };
    
    // generated by lib/categories.hs
    var word = "\\u0030-\\u0039\\u0041-\\u005a\\u005f\\u0061-\\u007a\\u00aa\\" +
        "u00b5\\u00ba\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u02c1\\u02c6-\\u" +
        "02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0300-\\u0374\\u0376\\u0377\\u037" +
        "a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5" +
        "\\u03f7-\\u0481\\u0483-\\u0487\\u048a-\\u0523\\u0531-\\u0556\\u0559" +
        "\\u0561-\\u0587\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u" +
        "05c7\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0610-\\u061a\\u0621-\\u065e\\u0" +
        "660-\\u0669\\u066e-\\u06d3\\u06d5-\\u06dc\\u06df-\\u06e8\\u06ea-\\u0" +
        "6fc\\u06ff\\u0710-\\u074a\\u074d-\\u07b1\\u07c0-\\u07f5\\u07fa\\u090" +
        "1-\\u0939\\u093c-\\u094d\\u0950-\\u0954\\u0958-\\u0963\\u0966-\\u096" +
        "f\\u0971\\u0972\\u097b-\\u097f\\u0981-\\u0983\\u0985-\\u098c\\u098f" +
        "\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bc-" +
        "\\u09c4\\u09c7\\u09c8\\u09cb-\\u09ce\\u09d7\\u09dc\\u09dd\\u09df-\\u" +
        "09e3\\u09e6-\\u09f1\\u0a01-\\u0a03\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a" +
        "13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39" +
        "\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a59-\\" +
        "u0a5c\\u0a5e\\u0a66-\\u0a75\\u0a81-\\u0a83\\u0a85-\\u0a8d\\u0a8f-\\u" +
        "0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0a" +
        "bc-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ad0\\u0ae0-\\u0ae3\\u0ae" +
        "6-\\u0aef\\u0b01-\\u0b03\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28" +
        "\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3c-\\u0b44\\u0b47\\" +
        "u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5c\\u0b5d\\u0b5f-\\u0b63\\u0b" +
        "66-\\u0b6f\\u0b71\\u0b82\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92" +
        "-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u" +
        "0baa\\u0bae-\\u0bb9\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0" +
        "bd0\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c05-\\u0c0c\\u0c0e-\\u0c" +
        "10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d-\\u0c44\\u0c4" +
        "6-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c58\\u0c59\\u0c60-\\u0c63" +
        "\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-" +
        "\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbc-\\u0cc4\\u0cc6-\\u0cc8" +
        "\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0cde\\u0ce0-\\u0ce3\\u0ce6-\\u0cef\\" +
        "u0d02\\u0d03\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d28\\u0d2a-\\u" +
        "0d39\\u0d3d-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4d\\u0d57\\u0d60-\\u0" +
        "d63\\u0d66-\\u0d6f\\u0d7a-\\u0d7f\\u0d82\\u0d83\\u0d85-\\u0d96\\u0d9" +
        "a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0dca\\u0dcf-\\u0dd4" +
        "\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e01-\\u0e3a\\u0e40-\\u0e4e\\" +
        "u0e50-\\u0e59\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e9" +
        "4-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab" +
        "\\u0ead-\\u0eb9\\u0ebb-\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0ec8-\\u0ecd" +
        "\\u0ed0-\\u0ed9\\u0edc\\u0edd\\u0f00\\u0f18\\u0f19\\u0f20-\\u0f29\\u" +
        "0f35\\u0f37\\u0f39\\u0f3e-\\u0f47\\u0f49-\\u0f6c\\u0f71-\\u0f84\\u0f" +
        "86-\\u0f8b\\u0f90-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1049\\u105" +
        "0-\\u1099\\u10a0-\\u10c5\\u10d0-\\u10fa\\u10fc\\u1100-\\u1159\\u115f" +
        "-\\u11a2\\u11a8-\\u11f9\\u1200-\\u1248\\u124a-\\u124d\\u1250-\\u1256" +
        "\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0" +
        "\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6" +
        "\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u135f\\u1380-\\u138f" +
        "\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u1676\\u1681-\\u169a\\u16a0-" +
        "\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1714\\u1720-\\u1734" +
        "\\u1740-\\u1753\\u1760-\\u176c\\u176e-\\u1770\\u1772\\u1773\\u1780-" +
        "\\u17b3\\u17b6-\\u17d3\\u17d7\\u17dc\\u17dd\\u17e0-\\u17e9\\u180b-\\" +
        "u180d\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18aa\\u1900-\\u191c\\u" +
        "1920-\\u192b\\u1930-\\u193b\\u1946-\\u196d\\u1970-\\u1974\\u1980-\\u" +
        "19a9\\u19b0-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a1b\\u1b00-\\u1b4b\\u1" +
        "b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1baa\\u1bae-\\u1bb9\\u1c00-\\u1" +
        "c37\\u1c40-\\u1c49\\u1c4d-\\u1c7d\\u1d00-\\u1de6\\u1dfe-\\u1f15\\u1f" +
        "18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5" +
        "b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-" +
        "\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec" +
        "\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u203f\\u2040\\u2054\\u2071\\u207f\\u" +
        "2090-\\u2094\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2102\\u2107\\u21" +
        "0a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d" +
        "\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188" +
        "\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2c6f\\u2c71-\\u2c7d\\u2c80-" +
        "\\u2ce4\\u2d00-\\u2d25\\u2d30-\\u2d65\\u2d6f\\u2d80-\\u2d96\\u2da0-" +
        "\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6" +
        "\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2de0-\\u2dff\\u2e2f" +
        "\\u3005-\\u3007\\u3021-\\u302f\\u3031-\\u3035\\u3038-\\u303c\\u3041-" +
        "\\u3096\\u3099\\u309a\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\" +
        "u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31b7\\u31f0-\\u31ff\\u3400-\\" +
        "u4db5\\u4e00-\\u9fc3\\ua000-\\ua48c\\ua500-\\ua60c\\ua610-\\ua62b\\u" +
        "a640-\\ua65f\\ua662-\\ua66f\\ua67c\\ua67d\\ua67f-\\ua697\\ua717-\\ua" +
        "71f\\ua722-\\ua788\\ua78b\\ua78c\\ua7fb-\\ua827\\ua840-\\ua873\\ua88" +
        "0-\\ua8c4\\ua8d0-\\ua8d9\\ua900-\\ua92d\\ua930-\\ua953\\uaa00-\\uaa3" +
        "6\\uaa40-\\uaa4d\\uaa50-\\uaa59\\uac00-\\ud7a3\\uf900-\\ufa2d\\ufa30" +
        "-\\ufa6a\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d-\\ufb28" +
        "\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\u" +
        "fb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\u" +
        "fdfb\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\ufe" +
        "70-\\ufe74\\ufe76-\\ufefc\\uff10-\\uff19\\uff21-\\uff3a\\uff3f\\uff4" +
        "1-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd" +
        "7\\uffda-\\uffdc";
    // parse plain text content and make urls and special tags clickable
    var htmlRegexp = new RegExp("(\\b(?:https?:\/\/|ftp:\/\/|mailto:|news\\\\.|www\\\\.)[-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#\/%=~_()|])|@(\\w+)|(#[" + word + "]+)", "gi");
    function parseHTML(content, oDiv) {
    	var mpos, lIndex = 0;
    	// iterate through results
    	while (mpos = htmlRegexp.exec(content)) {
    		// everything before
			oDiv.appendChild(newtext(content.substring(lIndex, mpos.index)));
			lIndex = mpos.index + mpos[0].length;
			var link = content.substring(mpos.index, lIndex); // the shown link text
			var href = link; // the real hred
			// twitter: @ or # links?
			if (mpos[2] || mpos[3]) {				
				href="http://www.twitter.com/" + (mpos[3] ? "#search?q=" : "") + encodeURIComponent(link);
			}
			var mn = newnode("a", { fontWeight: "bold"}, { href: href, target: "_blank" }, 
					[ newtext(link) ]);
			oDiv.appendChild(mn);
			// prevent stopEvent from grid
			jQuery(mn).bind("click", function(event) {
			    event.stopPropagation();
			});
    	}
    	// everything else
    	oDiv.appendChild(newtext(content.substring(lIndex, content.length)));
    };
    
    function MessagingGrids() {
    	this.container = { "list":null, "hsplit":null };
    	this.selection = selection = new Selection2();
    }
    
    MessagingGrids.prototype = {
    	initGrid: function(type, select_cb) {
	    	var grid = new LiveGrid2([{
	            text: "",
	            name: ["subject", "from", "receivedDate", "body", "headers", "picture"],
	            style: { height: "4.8em", borderBottom: "1px solid silver" },
	            set: function(div, content) {
	            	if (activeService.set) 
	            		activeService.set(div, content);
	            	else {
	            		var e = getElements(div);
		                e.picture.src = content.picture;	                
		                if (activeService.getSubject)                	
		                	activeService.getSubject(e, content);
		                else 
		                	e.from.firstChild.data = content.from ? content.from.personal
		                			: content.subject;
		                var date = content.receivedDate;
		                e.time.firstChild.data = date ?
		                    formatDate(date, isToday(date) ? "time" : "datetime") : "";
		                var body = getBody(content);
		                if (body.plain) {
		                    removeChildNodes(e.text);
		                    parseHTML(body.plain, e.text);
		                } else if (body.html) {
		                    e.text.innerHTML = body.html;
		                } else {
		                    removeChildNodes(e.text);
		                }
	            	}
	            },
	            clear:function(div) {
	            	if (activeService.clear) 
	            		activeService.clear(div);
	            	else {
	            		var e = getElements(div);
		                e.picture.src = getFullImgSrc("img/dummy.gif");
		                e.from.firstChild.data = "";
		                e.time.firstChild.data = "";
		                e.text.innerHTML = "";
	            	}
	            }
	        }], selection, "messaging/message");
	        grid.disablehover = true;
	        grid.contextmenu = new ContextMenu();
	        grid.getHeader();
	        grid.getTable($("messaging." + type + ".grid"));
	        if (select_cb) grid.events.register("Selected", select_cb);
	        return this.container[type] = grid;
    	},
    	disable: function() {
    		for (var i in this.container) {
    			if (this.container[i]) 
    				this.container[i].disable();
    		}
    	},
    	getGrid: function(type, select_cb) {
    		var grid = this.container[type] || this.initGrid(type, select_cb);    	
    		for (var i in this.container) {
    			$("messaging." + i).style.display = (type == i) ? "" : "none";
    		}
    		return grid;
    	}
    };
    
    function showDetails() {    	
    	
    	var msg = activeGrid.selection.getSelected()[0];
        var Self = this;
        ox.JSON.get(AjaxRoot +
            "/messaging/message?action=get" +
            "&id=" + encodeURIComponent(msg.id) + "&folder=" + encodeURIComponent(msg.folder) +
            "&session=" + session, function(message) {
        		var msg = message.data;
        		var date = msg.receivedDate;
        		$("messaging.hsplit.date").firstChild.data = date ?
	                    formatDate(date, isToday(date) ? "time" : "datetime") : "";
				if (msg.id) {
					var linked = newnode("a", 0, {href:msg.id, target:"_blank"}, [newtext(msg.subject)]);
					$("messaging.hsplit.subject").replaceChild(linked, $("messaging.hsplit.subject").firstChild);
				} else {
					$("messaging.hsplit.subject").firstChild.data = msg.subject || "";
				}
	        	var body = getBody(msg);
	        	if (body.html) {
	            	$("messaging.hsplit.detail").innerHTML = body.html;
	        	} else if (body.plain) {
	                removeChildNodes($("messaging.hsplit.detail"));
	                parseHTML(body.plain, $("messaging.hsplit.detail"));
	            } else {
	                removeChildNodes($("messaging.hsplit.detail"));
	            }
            });
    	
    }
    
    function changeFolder(type) {
        folderPath.drawDOMNode("messaging.foldername", activefolder);
        
        var service = /^(.*?):/.exec(activefolder);
        if (service) {
            service = service[1];
            messagingServices.get(setService);
        }
        // disable new icon big for RSS feeds
        ox.widgets.toolBar.tabs.messaging.children[0].setVisible(
            service !== "com.openexchange.messaging.rss");
        ox.widgets.toolBar.tabs.messaging.validate();
        
        
        
        function setService(serviceDefs) {
            activeService = allServices[service];
            if (!activeService || !(service in serviceDefs)) {
                activeService == null;
                return;
            }
            activeGrid = activeService.getGrid();
            activeGrid.contextmenu.removeAllItems();
            var actionDefs = serviceDefs[service].messagingActions;
            for (var i = 0; i < actionDefs.length; i++) {
                var item = activeService.actions &&
                           activeService.actions[actionDefs[i]];
                if (item) {
                    activeGrid.contextmenu.addItem(item.getContextMenuItem());
                }
            }
            activeGrid.contextmenu.display = activeGrid.contextmenu.items.length ?
                ContextMenu.prototype.display : emptyFunction;
            for (var i in allServices) {
                if(allServices[i].menuNode) {
                	allServices[i].menuNode.setVisible(i == service);
                }
            }
            Editor.selected(0);
            activeGrid.enable({ folder: activefolder });
        }
    }

    function Editor(action, title) {
        this.action = action;
        this.title = title;
        var Self = this;
        this.send_cb = function() { Self.send(); };
        this.done_cb = function() { Self.done(); };
    }
    
    Editor.menuID = 0;
    
    Editor.menuSections = {};
    
    Editor.selected = function(count) {
        var enabled = count == 1;
        for (var i in Editor.menuSections) {
            var section = Editor.menuSections[i];
            //@todo: change to new api
//            menuglobalzaehler = 0;
//            menuarrows.messaging[i] = [];
//            for (var j = 0; j < section.length; j++) {
//                menu_display_contents("messaging", i, enabled, section[j]);
//            }
//            showArrowPopUpMenu(i + ".enhancement", i, "messaging");
        }
    };
    
    Editor.prototype = {
        getContextMenuItem: function() {
            if (this.contextMenuItem) return this.contextMenuItem;
            this.contextMenuItem = new MenuItem(this.title, function() {
                this.editor.getMessage(this.getContext().getSelected()[0]);
            });
            this.contextMenuItem.editor = this;
            this.contextMenuItem.onShow = function() {
                this.setEnabled(this.getContext().count == 1);
            };
            return this.contextMenuItem;
        },
        createMenuItem: function(context) {
            var Self = this;
            var id = context.node.id;
            var section = Editor.menuSections[id];
            if (!section) section = Editor.menuSections[id] = [];
            section.push("messaging.menubutton." + Editor.menuID);
            MenuNodes.createSmallButton(context,
                "messaging.menubutton." + Editor.menuID++, this.title,
                getFullImgSrc("img/dummy.gif"), getFullImgSrc("img/dummy.gif"),
                function() {
                    Self.getMessage(activeGrid.selection.getSelected()[0]);
                });
        },
        getMessage: function(message) {
            this.edit({ contentType: { type: "text/plain" },
                        folder: activefolder, body: "" });
        },
        edit: function(message) {
            this.message = message;
            $("messaging.message").value = getBody(message).plain || "";
            $("messaging.to").style.display = "none";
            if (this.onEdit) this.onEdit();
            centerPopupWindow($("messaging.popup"));
            $("messaging.popup").style.display = "block";
            $("messaging.send").onclick = this.send_cb;
            setFocus($("messaging.message"));
        },
        send: function() {
            $("messaging.popup").style.display = "none";
            this.message.contentType = { type: "text/plain" };
            this.message.body = $("messaging.message").value;
            ox.JSON.put(AjaxRoot +
                "/messaging/message?action=perform&messageAction=" +
                this.action + "&folder=" + this.message.folder + "&session=" +
                session, this.message, this.done_cb);
        },
        done: function() { OXCache.update(); }
    };
    
    function MessageEditor(getAction, sendAction, title) {
        Editor.call(this, sendAction, title);
        this.getAction = getAction;
    }
    
    MessageEditor.prototype = extend(Editor, {
        getMessage: function(message) {
            var Self = this;
            ox.JSON.get(AjaxRoot +
                "/messaging/message?action=perform&messageAction=" +
                this.getAction + "&id=" + message.id + "&folder=" +
                message.folder + "&session=" + session, function(reply) {
                    Self.edit(reply.data);
                });
        }
    });
    
    var post = new Editor("post", _("Post"));
    post.getMessage = function(message) {
        this.edit({
            contentType: { type: "text/plain" },
            body: "",
            id: message.id,
            folder: message.folder,
            to: message.from
        });
    };
    post.onEdit = function() {
        $("messaging.to").parentNode.parentNode.style.display = "";
        $("messaging.to").value = this.message.to.personal;
    };
    var retweetNew = new Editor("tweet", _("Retweet new"));
    retweetNew.done = function() {
        ox.Configuration.info(_("Retweet sent successfully"));
    };
    
    var allServices = {
        "com.openexchange.messaging.facebook": {
            newMessage: new Editor("updateStatus"),
            actions: { post: post },
            getSubject: function(e, content) {
            	var mynode=newnode("a", { fontWeight:"bold" }, 
            			{ href: "http://www.facebook.com/people/" + (content.from ? content.from.personal : "") + 
            		+ (content.from ? "/" + content.from.address : "" ),
      			  target: "facebook" },
      			  [ newtext(content.from ? content.from.personal : content.subject) ]);
            	// replace current node
            	e.from.parentNode.replaceChild(mynode, e.from );
            	// prevent stopEvent from grid
            	mynode.onclick=function(e) {
            		cancelBubbling(e);
            	};
            },
            getGrid: function() {
            	return grids.getGrid("list");
            },
            getFolderIcons: function(folder) {
                return { open: getFullImgSrc("img/folder/facebook.png"),
                       closed: getFullImgSrc("img/folder/facebook.png") };
            }
        },
        "com.openexchange.messaging.rss": { 
            getSubject: function(e, content) {
            	e.from.parentNode.replaceChild(newnode("span", { fontWeight:"bold" }, 0,
            			[ newtext(content.from ? content.from.personal : content.subject) ]), e.from);
            },
            getGrid: function() {
            	return grids.getGrid("hsplit", showDetails);
            },
            getFolderIcons: function(folder) {
                return { open: getFullImgSrc("img/folder/rss.png"),
                       closed: getFullImgSrc("img/folder/rss.png") };
            }
        },
        "com.openexchange.messaging.twitter": {
            newMessage: new Editor("tweet"),
            actions: {
                retweet: new MessageEditor("retweet", "tweet", _("Retweet")),
                retweetNew: retweetNew,
                directMessage: new MessageEditor("directMessage", "tweet",
                    _("Direct message"))
            },
            getSubject: function(e, content) {
            	var mynode=newnode("a", { fontWeight:"bold" }, 
            			{ href: "http://www.twitter.com/" + (content.from ? content.from.address : ""),
      			  target: "twitter" },
      			  [ newtext(content.from ? content.from.personal : content.subject) ]);
            	// replace current node
            	e.from.parentNode.replaceChild(mynode, e.from);
            	// prevent stopEvent from grid
            	mynode.onclick=function(e) {
            		cancelBubbling(e);
            	};
            },
            getGrid: function() {
            	return grids.getGrid("list");
            },
            getFolderIcons: function(folder) {
                return { open: getFullImgSrc("img/folder/twitter.png"),
                       closed: getFullImgSrc("img/folder/twitter.png") };
            }
        }
    };
    
    customFolderIcons.messaging = function(folder) {
        var service = /^(.*?):/.exec(folder.id);
        if (service) return allServices[service[1]].getFolderIcons(folder);
        return { open: getFullImgSrc("img/folder/folder_opened.gif"),
               closed: getFullImgSrc("img/folder/folder_closed.gif") };
    };
    
})();