function onTwitterProfile(socnet, data) {
  if (data.error) {
    debugLog('onTwitterProfile error: '+data.error+'\n');
    resetTwitter();
    return;
  }
  if (data.screen_name) {
    socnet.add_me(data.screen_name);
  }
}

function get_twitter_profile(socnet) {
    var profile_callback = function(data) { onTwitterProfile(socnet, data); };
    var cbname = failsafe.make_cb(profile_callback, function () {
profile_callback({'error': 'Twitter fail whale; some HTML arrived where JSON was expected'})
      });
  var url = 'twitterOAuthCallback.php'+
            '?method=account/verify_credentials.json'+
            '&real_twitter_callback='+cbname+
            '&suppress_response_codes=1&callback=?';
  $.getJSON(url,
            function(result) {
                if (result.error) {
                    debugLog('ERROR: ' + result.error);
                    resetTwitter();
                } else {
                    inject_script(result.Location);
                }
            });
}

function get_twitter_loop(page, cursor, friends, cb) {
  if (page > 5) return cb({twitter_friends: friends, done: true})
  var url = 'twitterOAuthCallback.php'+
            '?method=statuses/friends.json'+
            '&cursor=' + cursor +
            '&suppress_response_codes=1&callback=?';
  $.getJSON(url,
            function(result) {
                debugLog(result.Location);
                var twitter_get_friends_loop_cb =
                function (data) {
                  if (data.error) {
                    return cb(data);
                  }
                  var done = !data.next_cursor;
                  cb({twitter_friends: data.users, done: done});
                  if (!done) {
                    get_twitter_loop(page+1, data.next_cursor, friends, cb);
                  }
                }
                var cbname = failsafe.make_cb(twitter_get_friends_loop_cb, function () {
twitter_get_friends_loop_cb({'error': 'Twitter fail whale; some HTML arrived where JSON was expected'})
                    });
                inject_script(result.Location + "&callback=" + cbname, twitter_get_friends_loop_cb)
            });
}

function twitter_get_friends_callback(socnet) {
    return function (data) {
        if (data.error) {
            debugLog('twitter_get_friends_callback error: '+data.error+'\n');
            resetTwitter();
            return;
        }


        var twitter_friends = data.twitter_friends;
        var vcards = [];
        for (var ii = 0; ii < twitter_friends.length; ii++) {
            var friend = twitter_friends[ii];
            var guessed_names = guess_names_from_string(friend.name);

            var tweet;
            if (friend.status) {
                tweet = {
                  id: friend.status.id,
                  created_at: friend.status.created_at,
                  text: htmlunescape(friend.status.text)
                };
            }

            vcards.push({
                  fn:           friend.name,
                 'given-name':  guessed_names['given-name'],
                 'family-name': guessed_names['family-name'],
                  photo:      friend.profile_image_url,
                  socnet:    'twitter',
                  favicon:   'http://twitter.com/favicon.ico',
                  url:       'http://twitter.com/' + friend.screen_name,
                  account_id: friend.id,
                  nickname:   friend.screen_name,
                  lastTweet:  tweet
            });
        }
        if (vcards.length) {
            socnet.add_vcards(vcards);
            if (data.done) socnet.set_state(state.loaded);
        } else {
            debugLog('NO Twitter contacts found!'+'\n');
            // XXX should we go to loaded state here?
        }
    };
}

function resetTwitter() {
  eraseCookie('knx_twitter_oauth_token_s');
  eraseCookie('knx_twitter_oauth_token');
  eraseCookie('knx_twitter');
  addr_book.socnet('twitter').set_state(state.unknown);
}

function twitter_attempt_fetch(socnet) {
  if (twitter_credentials_exist()) {
    if (socnet.state() === state.unknown) {
      socnet.set_state(state.loading);
      get_twitter_profile(socnet);
      get_twitter_loop(1, -1, [], twitter_get_friends_callback(socnet));
    }
  }
}

function twitter_credentials_exist() {
    return readCookie('knx_twitter_oauth_token') ? 1 : 0;
}

function twitter_attempt_foreground_fetch() {
    return twitter_attempt_fetch(addr_book.socnet('twitter'));
}

function checkTwitterCookie() {
  if (twitter_credentials_exist()) {
    clearInterval(window.twitterCheckr);
    window.twitterCheckr = null;
    twitter_attempt_foreground_fetch();
  }
}

function fetchFromTwitterNeedsAuth() {
  if (twitter_credentials_exist()) {
    twitter_attempt_foreground_fetch();
  } else {
    eraseCookie('knx_twitter_oauth_token_s');
    eraseCookie('knx_twitter');
    var d = new Date();
    createCookie('knx_windowid', d.getTime());
    window.twitterCheckr = setInterval(checkTwitterCookie, 100);
    return true;
  }
  return false;
}

function fetchFromTwitter() {
  if (fetchFromTwitterNeedsAuth()) {
    twitter_login = "twitterOAuthCallback.php?"+Math.round(Math.random()*100000);
    window.open(twitter_login, "twitterAuth", "height=400,width=800,toolbar=0,location=1,directory=0,resizable=1");
  }
}

knx.register_plugin({
    initialize: function() {
        addr_book.refetch_when_stale('twitter', twitter_attempt_fetch);
        twitter_attempt_foreground_fetch();
    },
    reset: resetTwitter
});
