/*
 * Scripts for Local Tweet.
 * $Id: local_tweet.js 35 2010-05-18 00:49:55Z kjsuzu $
 */

jQuery.noConflict();

var g_map;
var g_marker;
var g_circle;
var g_geocoder = new GClientGeocoder();

var g_latlng; // center of search
var g_radius = 5; // search radius (kilo meter)
var g_query = ''; // search keyword

var g_script_count = 0;
var g_current_search;
var g_tweets = []; // tweets cache
var g_current_position = 0; // position in cache
// flag to avoid click repeat
// there must be more elegant way
var g_retrieving = 0;
// timer ID to detect JSONP call timeout
var g_tid;

jQuery(document).ready(function() {
	jQuery('#radio').buttonset();
	jQuery('#slider').slider({
		min: 1,
		max: 50,
		value: g_radius,
		change: function (event, ui) {
			markerSet();
		},
		slide: function (event, ui) {
			drawCircle();
		}
	});
});

function initialize() {
	g_latlng = new GLatLng(geoip_latitude(), geoip_longitude());
	if (GBrowserIsCompatible()) {
		var options = {
			mapTypes: [G_NORMAL_MAP, G_SATELLITE_MAP, G_PHYSICAL_MAP],
			googleBarOptions: {
				showOnLoad: true,
				style: 'new',
				onGenerateMarkerHtmlCallback: function(marker) {
					markerSet(marker.getLatLng());
				},
				adsOptions: {
					client: $("gads_key").value
				}
			}
		}
		g_map = new GMap2($("map"), options);
		g_map.setCenter(g_latlng, 11);
		g_map.setUIToDefault();
		g_map.enableGoogleBar();
		g_map.disableDoubleClickZoom();

		g_marker = new GMarker(g_latlng, {draggable: true});

		GEvent.addListener(g_map, "dblclick", function(ovrlay, latlng) {
			markerSet(latlng);
		});
		GEvent.addListener(g_marker, "dragstart", function() {
			g_map.closeInfoWindow();
		});
		GEvent.addListener(g_marker, "dragend", function(latlng) {
			markerSet(latlng);
		});

		markerSet(g_latlng);
	}
}

// marker set/move including radius change
function markerSet(latlng) {
	g_map.clearOverlays();
	if ( latlng != null ) {
		g_marker.setLatLng(latlng);
	} else {
		var latlng = g_latlng;
	}
	g_map.addOverlay(g_marker);
	getAddress(latlng);
	drawCircle();
	refresh();
}

// get human readable address of latlng
function getAddress(latlng) {
	g_geocoder.getLocations(latlng, showAddress);
}

// display address on infoWindow (callback for GClientGeocoder#getLocations())
function showAddress(response) {
	if ( !response || response.Status.code != 200 ) {
	} else {
		var place = response.Placemark[0];
		g_map.closeInfoWindow();
		g_marker.openInfoWindowHtml(
			'<p class="address">' + place.address + '</p>'
		);
	}
}

// draw circle arround g_marker with slider specified radius
function drawCircle() {
	var latlng = g_marker.getLatLng();
	var radius = jQuery('#slider').slider('value');

	if ( g_circle != null ) {
		g_map.removeOverlay(g_circle);
		g_circle = null;
	}

	// get scale arround latlng
	var mPlat = latlng.distanceFrom(new GLatLng(latlng.lat()+1, latlng.lng())); // meter per latitude degree
	var mPlng = latlng.distanceFrom(new GLatLng(latlng.lat(), latlng.lng()+1)); // meter per longitude degree

	var edge = [];
	for (var i=0; i<=360; i+=5) {
		var dot = new GLatLng(latlng.lat() + (radius*1000/mPlat * Math.cos(i * Math.PI/180)),
				latlng.lng() + (radius*1000/mPlng * Math.sin(i * Math.PI/180)));
		edge.push(dot);
	}
	edge.push(edge[0]);
	g_circle = new GPolygon(edge, "#0055ff", 2, 1, "#0055ff", 0.2)
	g_map.addOverlay(g_circle);
}

// refresh search
function refresh() {
	if ( g_retrieving ) {
		return;
	}

	g_tweets = [];
	g_current_position = 0;
	g_current_search = null;

	showTweets();
}

// display next page
function next_page() {
	if ( g_retrieving ) {
		return;
	}

	showTweets();
}

// display previous page
function prev_page() {
	if ( g_retrieving ) {
		return;
	}

	g_current_position -= $("n_rows").value * 2;
	if ( g_current_position < 0 ) {
		g_current_position = 0;
	}

	showTweets();
}

// showing tweets starts here
function showTweets() {
	g_retrieving = 1;

	dispBlank();

	if ( g_current_position == 0 ) {
		$("btn_prev").setAttribute('class', 'btn05');
		$("btn_prev").setAttribute('src', 'asset/images/contents_btn05.png');
		$("btn_prev").setAttribute('onclick', '');
	} else {
		$("btn_prev").setAttribute('class', 'btn03');
		$("btn_prev").setAttribute('src', 'asset/images/contents_btn03.png');
		$("btn_prev").setAttribute('onclick', 'prev_page()');
	}
	$("btn_next").setAttribute('class', 'btn06');
	$("btn_next").setAttribute('src', 'asset/images/contents_btn06.png');
	$("btn_next").setAttribute('onclick', '');

	searchTweets();
}

// Search tweet untill cache has enough tweet to fill page
function searchTweets() {
	if ( !g_tweets[g_current_position + parseInt($("n_rows").value) - 1] ) {
		doSearchTweets();
		return;
	}

	doShowTweets();
}

// Execute search tweet by using twitter api
function doSearchTweets() {
	var old_script = $('script' + g_script_count);
	if ( old_script != null ) {
		old_script.remove();
	}
	g_script_count++;

	var src = "http://search.twitter.com/search.json";
	if ( g_current_search ) {
		src +=g_current_search.next_page;
	} else {
		var n_rows = $("n_rows").value;
		g_radius = jQuery('#slider').slider('value');
		g_latlng = g_marker.getLatLng();
		g_query = $("txt_search").value.replace(/(^\s+)|(\s+)$/g, "");

		src += "?rpp=" + n_rows + "&geocode=" + g_latlng.lat() + "%2C" + g_latlng.lng() + "%2C" + g_radius + "km";
		if ( g_query != '' && g_query != '検索ワードを入力してください' ) {
			src += "&q=" + g_query;
		}
	}
	src += "&callback=doneSearchTweets";
	src += "&lang=all";
	src += "&avoidcache=" + g_script_count;

	var script = document.createElement("script");
	script.setAttribute('type', 'text/javascript');
	script.setAttribute('charset', 'utf-8');
	script.setAttribute('id', 'script' + g_script_count);
	script.setAttribute('src', src);
	var head = document.getElementsByTagName('head').item(0);
	g_tid = setTimeout(searchTimeout, 5000);
	head.appendChild(script);
}

// search request timeout
function searchTimeout() {
	var script = $('script' + g_script_count);
	if ( script != null ) {
		script.remove();
	}

	doShowTweets();
}

// callback for twitter api call (doSearchTweets())
// puts tweets of search result to cache (g_tweets)
function doneSearchTweets(json_results) {
	clearTimeout(g_tid);

	var tweet;
	loop_tweets: while ( (tweet = json_results.results.shift()) ) {
		// skip if
		//   1. from_user ends with "bot"
		//   2. from_user is in g_bot_names
		//   3. source matches in g_sources as reg-exp
		if ( !$("show_bot").checked ) {
			if ( tweet.from_user.endsWith("bot") ) {
				continue loop_tweets;
			}
			var bot_names = $("bot_names").value.split(",");
			for ( var i=0; i < bot_names.length; i++ ) {
				if ( tweet.from_user == bot_names[i] ) {
					continue loop_tweets;
				}
			}
			var bot_sources = $("bot_sources").value.split(",");
			for ( var i=0; i < bot_sources.length; i++ ) {
				if ( tweet.source.match(new RegExp("^&lt;a .+&gt;" + bot_sources[i] + "&lt;/a&gt;$")) ) {
					continue loop_tweets;
				}
			}
		}
		tweet.source = tweet.source.gsub(/&lt;/, '<');
		tweet.source = tweet.source.gsub(/&gt;/, '>');
		tweet.source = tweet.source.gsub(/&quot;/, '"');
		g_tweets.push(tweet);
	}
	g_current_search = json_results;

	searchTweets();
}

// show tweets in cache
function doShowTweets() {
	$("sec02").innerHTML = '';

	var has_next = 1;
	for ( var i = 0; i < $("n_rows").value; i++ ) {
		if ( g_tweets[g_current_position] ) {
			dispOne(g_tweets[g_current_position]);
			g_current_position++;
		} else {
			if ( i == 0 ) {
				$("sec02").innerHTML = '\
			<div class="row01">\n\
				<div class="col01">&nbsp;</div>\n\
				<div class="col02">ツイートはありません</div>\n\
				<div class="col03">&nbsp;</div>\n\
			<!-- /#row01 --></div>\n';
			}
			has_next = 0;
		}
	}

	if ( has_next ) {
		$("btn_next").setAttribute('class', 'btn04');
		$("btn_next").setAttribute('src', 'asset/images/contents_btn04.png');
		$("btn_next").setAttribute('onclick', 'next_page()');
	}

	g_retrieving = 0;
}

// display one tweet in html
function dispOne(tweet) {
	var rowTmpl = new Template('\
			<div class="row01">\n\
				<div class="col01"><img src="#{profile_image_url}" alt="" width="58" height="58" /></div>\n\
				<div class="col02"><span class="span01"><a href="http://twitter.com/#{from_user}" target="_blank">#{from_user}</a> : </span>#{text}<br /><span class="span02">#{str_date} | #{source}から</span></div>\n\
				<div class="col03"><a href="http://twitter.com/?status=%40#{from_user}+" target="_blank"><img src="asset/images/contents_btn02.png" alt="このツイートに返信する" title="このツイートに返信する" width="21" height="20" /></a></div>\n\
			<!-- /#row01 --></div>\n');

	var now = Date();
	tweet.str_date = convertDate(tweet.created_at, now);
	$("sec02").innerHTML += rowTmpl.evaluate(tweet);
}

// display a blank field (prepare for retrieving)
function dispBlank() {
	$("sec02").innerHTML = '\
			<div class="row01">\n\
				<div class="col01">&nbsp;</div>\n\
				<div class="col02">&nbsp;</div>\n\
				<div class="col03">&nbsp;</div>\n\
			<!-- /#row01 --></div>\n';
}

// convert created_at to display string
function convertDate(at, now) {
	var time_diff = (Date.parse(now) - Date.parse(at)) / 1000;
	if ( time_diff < 60 ) {
		return '1分以内';
	} else if ( time_diff < 60*10 ) {
		return '約' + parseInt(time_diff/60) + '分前'; // per min
	} else if ( time_diff < 60*20 ) {
		return '約' + parseInt(time_diff/60/5)*5 + '分前'; // per 5mins
	} else if ( time_diff < 60*60 ) {
		return '約' + parseInt(time_diff/60/15)*15 + '分前'; // per 15mins
	} else if ( time_diff < 60*60*24 ) {
		return '約' + parseInt(time_diff/60/60) + '時間前'; // per hour
	} else if ( time_diff < 60*60*24*7 ) {
		return '約' + parseInt(time_diff/60/60/24) + '日前'; // per day
	} else {
		var d_at = new Date();
		d_at.setTime(Date.parse(at));
		return d_at.getYear() + '年' + (d_at.getMonth()+1) + '月' + d_at.getDate() + '日'
				+ ' ' + d_at.getHours() + ':' + d_at.getMinutes() + ':' + d_at.getSeconds();
	}
}

