// 初期化
$(function() {
	$('#start_btn').click(function() {
		$('#start').hide();
		$('#loading').show();
		getFollowers(-1);
	});
	$('#tabs > ul').tabs();
	getLimit();
});

var following = new Array();
var followers = new Array();
var followingPageCount = 0;
var followersPageCount = 0;
var errorCount = 0;
var view = true; // following: true, followers: false
var followingUrl = 'http://twitter.com/statuses/friends.json';
var followersUrl = 'http://twitter.com/statuses/followers.json';
var limitUrl = 'http://twitter.com/account/rate_limit_status.json';

function getFollowing(cursor) {
	followingPageCount++;
	$('#progress').html('Loading following (page ' + followingPageCount + ') ...');
	$.jsonp({
		url: followingUrl,
		data: { 'cursor': cursor },
		dataType: 'jsonp',
		callbackParameter: 'callback',
		timeout: 5000,
		success: function(data) {
			if(data.users) {
				$.each(data.users, function(i, user) {
					following[user.id] = user;
				});
				
				// 続きがある場合は次を読み込む
				if(data.next_cursor && data.next_cursor > 0) {
					getFollowing(data.next_cursor);
					
				// 取得し終わったら結果を表示する
				} else {
					setResult();
				}
			} else {
				errorCount++;
				alert('following の取得に失敗しました。following の取得を終了します。');
				setResult();
			}
		},
		error: function(xopt, status) {
			errorCount++;
			alert('following を取得中にエラーが発生しました。following の取得を終了します。');
			setResult();
		}
	});
}

// followers を取得する
function getFollowers(cursor) {
	followersPageCount++;
	$('#progress').html('Loading followers (page ' + followersPageCount + ') ...');
	$.jsonp({
		url: followersUrl,
		data: { 'cursor': cursor },
		dataType: 'jsonp',
		callbackParameter: 'callback',
		timeout: (followersPageCount == 1) ? 30000 : 5000,
		success: function(data) {
			
			// 取得成功時
			if(data.users) {
				$.each(data.users, function(i, user) {
					followers[user.id] = user;
				});
				
				// 続きがある場合は次を読み込む
				if(data.next_cursor && data.next_cursor != '0') {
					getFollowers(data.next_cursor);
					
				// 取得し終わったら following を取得する
				} else {
					getFollowing(-1);
				}
			
			// 取得失敗時
			} else {
				errorCount++;
				alert('followers の取得中にエラーが発生しました。followers の取得を終了し、following の取得を開始します。');
				getFollowing('-1');
			}
		},
		error: function(xopt, status) {
			errorCount++;
			alert('followers を取得できませんでした。followers の取得を終了し、following の取得を開始します。');
			getFollowing(-1);
		}
	});
}

// 結果を表示する
function setResult(view) {
	if(errorCount > 0) {
		alert('一部データの取得に失敗したため、取得分のみを表示します。follow している/されているの情報は正しくない可能性があります。');
	}
	
	$('#progress').html('drawing...');
	$('#following_result, #followers_result').hide();
	$('#following_result > tbody, #followers_result > tbody').empty();
	$('#tabs').show();
	$('#following_title').html('following (' + getArrayLength(following) + ')');
	$('#followers_title').html('followers (' + getArrayLength(followers) + ')');
	
	setData(true);
	setData(false);
	
	$('#loading').hide();
	$('#progress').empty();
	
	// テーブルを表示し、ソートする
	$('#following_result').show();
	var following_count = $('#following_result tbody tr').length;
	if(following_count > 0) {
		$('#following_result').tablesorter({
			sortList: [[0, 0]],
			widgets: ['zebra'],
			headers: {
				1: { sorter: false },
				4: { sorter: false },
				5: { sorter: false }
			}
		}).tablesorterPager({
			container: $('#following_pager'),
			size: 20,
			positionFixed: false
		});
		$('#following_pager form select').append('<option value="' + following_count + '">all</option>');
	} else {
		$('#following_result tbody').html('<tr><td colspan="9" style="text-align: center;"><span>No data.</span></td></tr>');
	}	
	
	$('#followers_result').show();
	var followers_count = $('#followers_result tbody tr').length;
	if(followers_count > 0) {
		$('#followers_result').tablesorter({
			sortList: [[0, 0]],
			widgets: ['zebra'],
			headers: {
				1: { sorter: false },
				4: { sorter: false },
				5: { sorter: false },
				6: { sorter: 'digit' },
				7: { sorter: 'digit' }
			}
		}).tablesorterPager({
			container: $('#followers_pager'),
			size: 20,
			positionFixed: false
		});
		$('#followers_pager form select').append('<option value="' + followers_count + '">all</option>');
	} else {
		$('#followers_result tbody').html('<tr><td colspan="9" style="text-align: center;"><span>No data.</span></td></tr>');
	}
}

function setData(view) {
	var tbl = (view) ? $('#following_result') : $('#followers_result');
	
	// ベースにするデータを格納する
	var list = (view) ? following : followers;
	var list2 = (view) ? followers : following;
	
	// following, followers を描画する
	for (key in list) {
		var html = '<tr>';
		
		// id
		html += '<td class="id">' + list[key].id + '</td>';
		
		// image
		html += '<td class="image">';
		html += 	'<a href="http://twitter.com/' + list[key].screen_name + '" target="_blank">';
		html += 		'<img src="' + list[key].profile_image_url + '" class="icon" width="24" height="24" alt="" />';
		html += 	'</a>';
		html += '</td>';
		
		// screen_name
		html += '<td class="screen_name">';
		html += 	'<a href="http://twitter.com/' + list[key].screen_name + '" target="_blank">' + list[key].screen_name + '</a>';
		html += '</td>';
		
		// name
		html += '<td class="name">';
		html += list[key].name;
		if(list[key].protected) {
			html += '<img src="img/protected.gif" class="icon_protected" width="12" height="15" alt="" />';
		}
		html += '</td>';
		
		// web
		html += '<td class="web">';
		if(list[key].url) {
			html += '<a href="' + list[key].url + '" target="_blank">web</a>';
		}
		html += '</td>';
		
		// bio
		html += '<td class="bio">';
		if(list[key].description) {
			html += createLink(list[key].description);
		}
		html += '</td>';
		
		// following_count
		html += '<td class="following_count">' + list[key].friends_count + '</td>';
		
		// followers_count
		html += '<td class="followers_count">' + list[key].followers_count + '</td>';
		
		// last_updated
		html += '<td class="last_updated">';
		if(list[key].status) {
			var d = new Date(Date.parse(list[key].status.created_at));
			if(d) {
				html += d.getFullYear() + "-" + padZero(d.getMonth() + 1) + "-" + padZero(d.getDate());
			} else {
				html += '(error)';
			}
		} else {
			html += 'N/A';
		}
		html += '</td>';
		
		// follow
		html += '<td class="follow">';
		if(list2[list[key].id]) {
			html += 'follow';
		} else {
			html += 'not follow';
		}
		html += '</td>';
		
		html += '</tr>';
		tbl.append(html);
	}
}

// API 制限を取得する
function getLimit() {
	$.ajax({
		url: limitUrl,
		type: 'GET',
		dataType: 'jsonp',
		cache: false,
		success: function(result) {
			$('#limit_count').html(result.remaining_hits + '/' + result.hourly_limit);
			if(result.remaining_hits <= 20) {
				var d = new Date(Date.parse(result.reset_time));
				$('#limit_count').after(' (' + d.getFullYear() + '-' + padZero(d.getMonth() + 1) + '-' + padZero(d.getDate()) + ' ' + padZero(d.getHours()) + ':' + padZero(d.getMinutes()) + ' にリセットされます)');
			}
		},
		error: function(xhr, status, err) {
			alert('エラーが発生しました: ' + status);
		}
	});
}

// 連想配列の要素数を取得する
function getArrayLength(array) {
	var i = 0;
	for(key in array) { i++; }
	return i;
}

// 数値を 3 桁区切りのカンマにする
function addFigure(str) {
	var num = new String(str).replace(/,/g, "");
	while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
	return num;
}

function padZero(s) {
	return ("0" + s).slice(-2);
}

function createLink(s) {
	return s.replace(/(https?:\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)/ig, "<a href='$1' target='_blank'>$1</a>");
}