// ==UserScript==
// @name           FavotterFavor
// @namespace      http://twitter.com/kosugi
// @include        http://favotter.matope.com/*
// @include        http://twitter.1x1.jp/search/*
// @description    allows you to favor posts on the Favotter / Twitter 検索
// ==/UserScript==
//
// version: 2008-06-27T09:28:58+09:00
// author:  KOSUGI Tomo (kosugi dot tomo at gmail dot com)
// license: GPL <http://www.gnu.org/copyleft/gpl.html>
//

new function() {

    var sites = {
        'http://favotter.matope.com/': {
            'posts': 'descendant::div[@class="info meta entry-meta"]',
            handler: function() {
                var p = /.*id=/;
                return function(node) {
                    var postId = document.evaluate('descendant::a[@class="taggedlink"]/@href', node, null, XPathResult.STRING_TYPE, null).stringValue.replace(p, '');
                    var target = node.getElementsByTagName('strong')[0];
                    var name = target.getElementsByTagName('a')[0].title;
                    target.insertBefore(onAfterStarClick(properties.destroy, postId), target.firstChild);
                    target.insertBefore(createPermalink(postId, name), target.firstChild);
                }
            }()
        },
        'http://twitter.1x1.jp/search/': {
            'posts': 'descendant-or-self::table[@class="list"]//tr',
            handler: function() {
                var p = /^http:\/\/twitter\.com\/(.*?)\/statuses\/(.*)/;
                return function(node) {
                    var container = node.getElementsByTagName('td')[4];
                    var a = container.getElementsByTagName('a')[0];
                    var tmp = a.href.match(p);
                    var name = tmp[1];
                    var postId = tmp[2];
                    node.getElementsByTagName('img')[0].alt = name;
                    container.style.whiteSpace = 'nowrap';
                    container.appendChild(createPermalink(postId, name));
                    container.appendChild(onAfterStarClick(properties.destroy, postId));
                    container.removeChild(a);
                }
            }()
        }
    }

    var siteinfo;
    for (url in sites) {
        if (0 == window.location.href.indexOf(url)) {
            siteinfo = sites[url];
            break;
        }
    }

    if (!siteinfo) return;

    var createPermalink = function(postId, name) {
        var permalink = document.createElement('a');
        permalink.href = 'http://twitter.com/' + encodeURIComponent(name) + '/statuses/' + encodeURIComponent(postId);
        permalink.title = 'permalink@twitter';
        permalink.appendChild(createImage('http://assets1.twitter.com/images/favicon.ico', 'pointer', 'permalink@twitter'));
        return permalink;
    }

    var createImage = function(url, cursorStyle, title) {
        var image = new Image();
        image.src = url;
        image.title = title;
        image.style.cursor = cursorStyle;
        image.style.verticalAlign = 'middle';
        return image;
    }

    var properties = {
        create: {
            newMethod: 'destroy',
            newIconUrl: 'http://assets0.twitter.com/images/icon_star_full.gif',
            newTitle: 'unfavor this post',
            progressMsg: 'favoring...'
        },
        destroy: {
            newMethod: 'create',
            newIconUrl: 'http://assets2.twitter.com/images/icon_star_empty.gif',
            newTitle: 'favor this post',
            progressMsg: 'unfavoring...'
        }
    }

    var onStarClick = function(event) {
        var oldIcon = event.srcElement || event.target;
        var groups = oldIcon.id.match(/^[^_]+_([^_]+)_(.*)$/);
        var method = groups[1];
        var postId = groups[2];
        var property = properties[method];

        var newIcon = createImage('http://twitter.com/images/icon_throbber.gif', 'progress', property.progressMsg);
        oldIcon.parentNode.replaceChild(newIcon, oldIcon);

        var iframe = document.createElement('iframe');
        iframe.width = 0;
        iframe.height = 0;
        iframe.src = 'http://twitter.com/favourings/' + encodeURIComponent(method) + '/' + encodeURIComponent(postId);
        document.body.appendChild(iframe);
        var timer_id = setInterval(function() {
            var doc = iframe.contentDocument || iframe.contentWindow.document;
            try {
                doc.body.innerHTML;
            }
            catch (e) {
                // これでロード完了と見做す (かなり乱暴)
                clearInterval(timer_id);
                document.body.removeChild(iframe);
                onAfterStarClick(property, postId, newIcon);
            }
        }, 500);
    }

    var onAfterStarClick = function(property, postId, oldIcon) {
        var newIcon = createImage(property.newIconUrl, 'pointer', property.newTitle);
        newIcon.id = 'favotterFavorId_' + property.newMethod + '_' + postId;
        newIcon.addEventListener('click', onStarClick, false);
        if (oldIcon)
            oldIcon.parentNode.replaceChild(newIcon, oldIcon);
        return newIcon;
    }

    var doIt = function(targetNode) {
        var postNodes = document.evaluate(siteinfo.posts, targetNode, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var n = 0, len = postNodes.snapshotLength; n < len; ++n) {
            siteinfo.handler(postNodes.snapshotItem(n));
        }
    }

    setTimeout(function() {
        if (window.AutoPagerize && window.AutoPagerize.addFilter) {
            window.AutoPagerize.addFilter(function(ctx) {
                ctx.forEach(function(node) { doIt(node); });
            });
        }
    }, 0);

    doIt(document);
}
