var MailSafe = {
    /**
     * Encode an email address
     *
     * @param  string   value  Email address encode
     * @param  integer  key    Key (0-254) used to encode email
     * @return string  Encoded email address
     */
    encode: function(value, key) {
        var len = value.length;
        var toHex = this._toHex;
        var result = toHex(key);
        for (var idx = 0; idx < len; idx++){
            var code = toHex(key ^ value.charCodeAt(idx));
            result += (code.length != 2 ? '0' : '') + code;
        }
        return result;
    },
    
    /**
     * Decode email address
     *
     * @param  string  hash  Encoded email address to decode
     * @return string  Decoded email address.
     */
    decode: function(hash) {
        var len = hash.length;
        if (len < 4 || (len % 2 != 0)) return '';
        var fromHex = this._fromHex;
        var key = fromHex(hash.substr(0,2));
        var result = '';
        for(var idx = 2; idx < len; idx += 2){
            var code = fromHex(hash.substr(idx, 2)) ^ key;
            result += String.fromCharCode(code);
        }
        return result;
    },
    
    /**
     * Render a hashed email address as straight text
     *
     * @param  string  hash  Encoded email address to decode
     */
    renderText: function(hash) {
        document.write(this.decode(hash));
    },
    
    /**
     * Render a hashed email address as a anchor
     *
     * @param  string  hash     Encoded email address to decode
     * @param  string  options  Additional options
     */
    renderLink: function(hash, options) {
        options = options || {};
        var address = this.decode(hash);
        document.write('<a href="mailto:' + address + 
            (options.subject ? '?subject=' + encodeURIComponent(options.subject) : '') + '"' +
            (options.title ? ' title="' + options.title + '"' : '') +
            (options.target ? ' target="' + options.target + '"' : '') + '>' +
            (options.content ? options.content : address) + '</a>');
    },
    
    _toHex: function(value) { 
        var result = value.toString(16);
        return (result.length != 2 ? '0' : '') + result;
    },
    
    _fromHex: function(value) {
        return parseInt('0x' + value);
    }
};
