// WebmailCompose UserJS for Opera
// Copyright Michael A. Puls II, <http://shadow2531.com/opera/userjs/BeforeMailtoURL.js>
// Distributed under the Boost Software License, Version 1.0. <http://boost.org/LICENSE_1_0.txt>
// Contact: <mailto:%22Michael%20A.%20Puls%20II%22%20%3Cshadow2531%40gmail.com%3E?subject=BeforeMailtoURL%20UserJS>
// Test: <http://shadow2531.com/opera/testcases/mailto/modern_mailto_uri_scheme.html#test>
// Documentation: <http://shadow2531.com/opera/userjs/BeforeMailtoURL.txt>
// Use with <http://shadow2531.com/opera/userjs/MailtoDecodedTooltip.js> if you like.
// Build 16

(function(){
    var on = true;
    var activeClient = "Gmail";
    var supportTargetAttribute = false;
    var supportForms = false;
    var clients = {
        "Gmail"         : "http://mail.google.com/mail/?compose=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail_https"   : "https://mail.google.com/mail/?compose=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail1"        : "http://mail.google.com/mail/?ui=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail1_https"  : "https://mail.google.com/mail/?ui=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail2"        : "http://mail.google.com/mail/?ui=2&nocheckbrowser&compose=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail2_https"  : "https://mail.google.com/mail/?ui=2&nocheckbrowser&compose=1&view=cm&fs=1&to=%T&su=%S&body=%M&cc=%C&bcc=%B",
        "Gmail_uri"     : "https://mail.google.com/mail/?extsrc=mailto&url=%w",
        "Operamail"     : "http://mymail.operamail.com/scripts/mail/Outblaze.mail?compose=1&did=1&a=1&to=%T&subject=%S&body=%M&cc=%C&bcc=%B",
        "Fastmail"      : "https://www.fastmail.fm/mail/?MSignal=MC-FromName**&to=%T&cc=%C&bcc=%B&subject=%S&body=%M",
        "Fastmail_uri"  : "https://www.fastmail.fm/action/compose/?mailto=%w",
        "Hotmail"       : "http://mail.live.com/mail/EditMessageLight.aspx?n=&to=%T&cc=%C&bcc=%B&subject=%S&body=%M",
        "Yahoo_generic" : "http://us.mg1.mail.yahoo.com/mc/compose?ymv=0&body=%M&Subj=%S&to=%T&cc=%C&bcc=%B",
        "Yahoo"         : "http://compose.mail.yahoo.com/?To=%T&Subj=%S&Cc=%C&Bcc=%B&Body=%M",
        "Yahoo_server"  : "http://us.mg1.mail.yahoo.com/dc/launch?sysreq=ignore&action=compose&login=1&To=%T&Subj=%S&Cc=%C&Bcc=%B&Body=%M",
        "Yahoo_classic_plain_text_mode_workaround" : "http://shadow2531.com/opera/testcases/registerProtocolHandler/yahoo_mail.html?uri=%w",
        "SquirrelMail"  : "http://your_squirrelmail_server.com/src/compose.php?send_to=%T&subject=%S&body=%M&send_to_cc=%C&send_to_bcc=%B",
        "Horde"         : "http://your_horde_server.com/horde/imp/compose.php?popup=0&to=%T&cc=%C&msg=%M&subject=%S&bcc=%B",
        "Mail.com"      : "http://mail01.mail.com/scripts/mail/Outblaze.mail?composeto=%T&subject=%S&body=%M&cc=%C&bcc=%B&compose=1",
        "Yandex"        : "http://mail.yandex.ru/compose?mailto=%w",
        "Mail.ru"       : "http://win.mail.ru/cgi-bin/sentmsg?To=%T&CC=%C&BCC=%B&Subject=%S&BodyUTF8=%M&accel=1",
        "RoundCube"     : "http://your_roundcubemail_server/?_task=mail&_action=compose&_to=%T&_subject=%S&_body=%M&_cc=%C&_bcc=%B"
    };

    function MailtoURIParser(uri) {
        uri = "to=" + uri.substr(7);
        var qm = uri.indexOf('?');
        if (qm != -1) {
            var query = uri.substr(qm + 1);
            uri = uri.substring(0, qm).replace(/&/g, "%26");
            if (query != "") {
                uri += "&" + query;
            }
        } else {
            uri = uri.replace(/&/g, "%26");
        }
        this.parse(this.escapeInvalidHH(uri));
    }
    MailtoURIParser.prototype = {
        parse : function (dataset) {
            this.to = this.subject = this.body = this.cc = this.bcc = "";
            var ref = this;
            dataset.replace(/([^=&]+)=([^&]*)/g, function(match, hname, hvalue){
                hname = ref.decode(hname).toLowerCase();
                if (hname == "to") {
                    if (hvalue != "") {
                        if (ref.to != "")
                            ref.to += "%2C%20";
                        ref.to += hvalue;
                    }
                } else if (hname == "cc") {
                    if (hvalue != "") {
                        if (ref.cc != "")
                            ref.cc += "%2C%20";
                        ref.cc += hvalue;
                    }
                } else if (hname == "bcc") {
                    if (hvalue != "") {
                        if (ref.bcc != "")
                            ref.bcc += "%2C%20";
                        ref.bcc += hvalue;
                    }
                } else if (hname == "subject") {
                    ref.subject = hvalue;
                } else if (hname == "body") {
                    if (!(hvalue == "" && ref.body == "")) {
                        if (ref.body != "")
                            ref.body += "%0D%0A";
                        ref.body += hvalue;
                    }
                }
            });
            this.to = this.encode(this.filterLine(this.decode(this.to)));
            this.subject = this.encode(this.filterLine(this.decode(this.subject)));
            this.body = this.encode(this.filterMultiLine(this.decode(this.body)));
            this.cc = this.encode(this.filterLine(this.decode(this.cc)));
            this.bcc = this.encode(this.filterLine(this.decode(this.bcc)));
        },
        encode : function(s) {
            try {
                return encodeURIComponent(s.replace(/\n/g, "\r\n"));
            } catch (e) {
                return "";
            }
        },
        decode : function(s) {
            try {
                return decodeURIComponent(s).replace(/(\r\n|\r)/g, '\n');
            } catch (e) {
                return "";
            }
        },
        format : function(s) {
            var ref = this;
            return s.replace(/(%%)|(%T)|(%S)|(%M)|(%C)|(%B)|(%w)/g, function(match, a, b, c, d, e, f, g) {
                if (a) return "%";
                if (b) return ref.to;
                if (c) return ref.subject;
                if (d) return ref.body;
                if (e) return ref.cc;
                if (f) return ref.bcc;
                if (g) return ref.encode("mailto:" + ref.to + "?subject=" + ref.subject + "&body=" + ref.body + "&cc=" + ref.cc + "&bcc=" + ref.bcc);
            });
        },
        filterLine : function(s) {
            var ref = this;
            return s.replace(/([\x00-\x08]|[\x0A-\x1F])/g, function(match) {
                if (match == "\r" || match == "\n") return "";
                return ref.encode(match);
            });
        },
        filterMultiLine : function(s) {
            var ref = this;
            return s.replace(/[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]/g, function(match) {
                return ref.encode(match);
            });
        },
        escapeInvalidHH : function(s) {
            return s.replace(/%(?![0-9A-F]{2})/gi, function() {
                return "%25";
            });
        }
    };
    function trim(s) {
        return s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    }
    function createMailtoURIFromEnabledFormControls(form) {
        var uri = "mailto:?";
        var skip = true;
        var el = form.elements;
        for (var i = 0; i < el.length; ++i) {
            if (el[i].disabled || !el[i].name)
                continue;
            if (el[i] instanceof HTMLObjectElement && !el[i].value)
                continue;
            if (el[i] instanceof HTMLInputElement && (el[i].type == "checkbox" || el[i].type == "radio") && !el[i].checked)
                continue;
            var hname, hvalue;
            try {
                hname = encodeURIComponent(el[i].name);
                hvalue = encodeURIComponent(el[i].value);
            } catch (err) {
                continue;
            }
            if (!skip)
                uri += '&';
            uri += hname;
            uri += '=';
            uri += hvalue;
            skip = false;
        }
        if (form.method == "post") {
            var existing = "to=" + trim(form.getAttribute("action")).substr(7).replace(/\?/, "&").replace(/^&+|&+$/g, "").replace(/\+/g, "%2B");
            var ret = "mailto:?subject=";
            ret += "Form%20Post%20from%20Opera";
            if (existing != "") {
                ret += '&';
                ret += existing;
            }
            ret += "&body=";
            try {
                ret += encodeURIComponent(uri.substr(8));
            } catch (err) {

            }
            return ret;
        }
        return uri;
    }
    function loadURI(uri, target) {
        if (!supportTargetAttribute || typeof target != "string" || target == "")
            target = "_blank";
        var parser = new MailtoURIParser(uri);
        var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
        a.href = parser.format(clients[activeClient]);
        a.target = target;
        a.click();
    }
    if (on) {
        window.opera.addEventListener("BeforeEvent.click", function(e) {
            var ev = e.event;
            var el = ev.target;
            if (ev.button == 0) {
                var isLink = el instanceof HTMLAnchorElement;
                if (!isLink) {
                    var parentLevel = 0;
                    while (el.parentNode) {
                        if (el.parentNode instanceof HTMLAnchorElement) {
                            el = el.parentNode;
                            isLink = true;
                            break;
                        }
                        el = el.parentNode;
                        if (parentLevel == 20) {
                            break;
                        }
                        ++parentLevel;
                    }
                }
                if (isLink) {
                    var href = trim(el.getAttribute("href"));
                    if (href.search(/mailto:/i) == 0) {
                        ev.preventDefault();
                        loadURI(href, el.target);
                    }
                }
            }
        }, false);
        if (supportForms) {
            window.opera.addEventListener("BeforeEvent.submit", function(e) {
                var ev = e.event;
                var el = ev.target;
                if (el instanceof HTMLFormElement && el.action && el.action.search(/mailto:/i) == 0) {
                    ev.preventDefault();
                    loadURI(createMailtoURIFromEnabledFormControls(el), el.target);
                }
            }, false);
        }
    }
})();