/**
 * @file tabelog.js
 * @brief 価格コムの提供するレストラン情報取得APIを利用するJavaScriptファイル
 * @note http://r.tabelog.com/help/api
 *
 * @author kinokorori
 * @date 2008. 8. 5 ～ 2008. 10. 31
 */

var RESTAURANT_GETMAX = 300;
var PROXY_URL = "http://hiyoshisv.blogdns.com/tabesta/cgi-bin/proxy.php";
var RANGE_SMALL=0;
var RANGE_MEDIUM=1;
var RANGE_LARGE=2;

/**
 * @brief レストラン情報格納クラス
 * @param[in] url_ レストランURL
 * @param[in] name_ 店名
 * @param[in] category_ カテゴリ
 * @param[in] lat_ 緯度(latitude)
 * @param[in] lon_ 経度(longitude)
 * @param[in] totalScore_ 総合評価
 * @param[in] tasteScore_ 味評価
 * @param[in] serviceScore_ サービス評価
 * @param[in] moodScore_ 雰囲気評価
 * @param[in] dinner_ ディナー予算
 * @param[in] lunch_ ランチ予算
 */
function restInfo(url_, name_, category_, lat_, lon_, totalScore_, 
 tasteScore_, serviceScore_, moodScore_, dinner_, lunch_, business_, holiday_)
{
	this.url = url_;
	this.name = name_;
	this.category = category_;
	this.longitude = lon_;
	this.latitude = lat_;
	this.totalScore = totalScore_;
	this.tasteScore = tasteScore_;
	this.serviceScore = serviceScore_;
	this.moodScore = moodScore_;
	this.dinnerPrice = dinner_;
	this.lunchPrice = lunch_;
	this.business = business_;
	this.holiday = holiday_;
	//mapCtrl.addPin(lat_, lon_);
}

/**
 * @brief カテゴリ情報格納クラスのコンストラクタ
 */
function categoryInfomation()
{
	this.categoryItem = new Object();
	this.totalCount = 0;
	this.highlightAllCategory = true;
	this.currentPage = 1;
}

/**
 * @brief レストラン検索マネージャのコンストラクタ
 */
var tabelogManager = new function()
{
	this.restArray = new Array();
	this.categoryInfo = new categoryInfomation();
	this.forMsgTag = "shopSearch";
	this.currentPage = 0;
	this.totalResult = 0;
	this.threshTotalScore = 0;
	this.clearId = 0;
	this.searchLat = 0;
	this.searchLon = 0;
	this.searchRange = RANGE_MEDIUM;
	this.searchedRange = RANGE_MEDIUM;
}


/**
 * @brief 検索を開始します
 * @param[in] lat 緯度
 * @param[in] lon 経度
 */
tabelogManager.newSearch = function(lat, lon)
{
	if (mainCanvas == null) { return; }
	clearTimeout(this.clearId);
	clearAppendXaml();
	this.currentPage = 1;
	this.totalResult = 0;
	this.searchLat = lat;
	this.searchLon = lon;
	delete this.restArray;
	this.restArray = new Array();
	delete this.categoryInfo;
	this.categoryInfo = new categoryInfomation();
	this.searchedRange = this.searchRange;
	
	this.showSearchRange(mainCanvas, true);
	var infoTxt = mainCanvas.findName("RestInfoText").setValue("Text", " ");
	mainCanvas.findName("NowLoadingIcon").setValue("Visibility", "Visible");
	mainCanvas.findName("TotalRestaurant").setValue("Text", "[---/---]");
	this.nextSearch();
}

/**
 * @brief 次のページの情報を取得します
 */
tabelogManager.nextSearch = function()
{
	//$(this.forMsgTag).innerHTML = "レストランを検索しています";
	var url = "http://api.tabelog.com/Ver2.1/RestaurantSearch/";
	pars = "Key=" + appkey['key'];
	pars += "&Latitude=" + this.searchLat;
	pars += "&Longitude=" + this.searchLon;
	if (this.searchedRange == RANGE_SMALL) {
		pars += "&SearchRange=small";
	} else if (this.searchedRange == RANGE_MEDIUM) {
		pars += "&SearchRange=medium";
	} else {
		pars += "&SearchRange=large";
	}
	pars += "&ResultSet=large";
	pars += "&PageNum=" + this.currentPage;
	
/*
	if (navigator.appName == "Netscape") {
		try {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
		} catch(e) {
			alert(e);
			return;
		}
	}
*/

	//this.showXML(url+"?"+pars);

	var proxy_pars = "proxy_url=" + encodeURIComponent(url + "?" + pars);
	//url = PROXY_URL;
	//ajaxのparametersに設定する

	var ajax = new Ajax.Request(PROXY_URL,
		{
			method: 'get',
			parameters: proxy_pars,
			onComplete: this.completeAjax,
			onSuccess: this.succeededAjax,
			onFailure: this.failedAjax
		});
}

tabelogManager.showXML = function(url)
{
	var win = window.open(url, "", "width=640,height=480,toolbar=1,resizable=1,scrollbars=1");
}

tabelogManager.completeAjax = function(req)
{
}

tabelogManager.succeededAjax = function(req)
{
	var offset = tabelogManager.restArray.length;
	tabelogManager.getRestaurantInfo(req);
	var xaml = tabelogManager.createXAML(offset);
	appendXaml(xaml);
	tabelogManager.currentPage++;
}

this.failedAjax = function(req)
{
	//$(tabelogManager.forMsgTag).innerHTML = "レストランの検索に失敗しました。";
}


tabelogManager.getRestaurantInfo = function(req)
{
	var xmlData = req.responseXML;
	if (!xmlData) { return; }
	
	var errorNodes = xmlData.getElementsByTagName("Error");
	if (errorNodes.length != 0) {
		this.showError(errorNodes[0]);
		mainCanvas.findName("NowLoadingIcon").setValue("Visibility", "Collapsed");
		return;
	}
	
	var resultNodes = xmlData.getElementsByTagName("NumOfResult");
	if (resultNodes.length == 0) { 
		mainCanvas.findName("NowLoadingIcon").setValue("Visibility", "Collapsed");
		//$(this.forMsgTag).innerHTML = "NumOfResultが取得できませんでした。";
		return;
	}
	
	this.totalResult = parseInt(resultNodes[0].firstChild.nodeValue);
	if (this.totalResult == 0) {
		mainCanvas.findName("NowLoadingIcon").setValue("Visibility", "Collapsed");
		//$(this.forMsgTag).innerHTML = "近くのレストラン情報がありません。";
		return;
	}
	

	this.getDataFromXML(xmlData);

	var progBar = mainCanvas.findName("ProgressBar");
	var restMax = (this.totalResult > RESTAURANT_GETMAX) ? RESTAURANT_GETMAX : this.totalResult;
	progBar.setValue("Width", Math.round(this.restArray.length / restMax * BLOCKWIDTH));
	var progBarFill = mainCanvas.findName("ProgBarColor");
	progBarFill.setValue("Color", "#a000ff00");

	if (this.totalResult > this.restArray.length && this.restArray.length < RESTAURANT_GETMAX) {
		this.clearId = setTimeout("tabelogManager.nextSearch()", 500);
		//this.nextSearch();
	} else {
		mainCanvas.findName("ProgBarFadeOut").begin();
		mainCanvas.findName("NowLoadingIcon").setValue("Visibility", "Collapsed");
	}
	
	var totalRestaurantTxt = mainCanvas.findName("TotalRestaurant");
	var textArrange = function(num) {
		var txt = "";
		if (num < 10) { txt = "  " + num; }
		else if (num < 100) { txt = " " + num; }
		else { txt = "" + num; }
		return txt;
	}
	var currentProgress = "[" + textArrange(this.restArray.length) + "/" + textArrange(restMax) + "]";
	totalRestaurantTxt.setValue("Text", currentProgress);
}

tabelogManager.getDataFromXML = function(xmlData)
{
	var itemNodes = xmlData.getElementsByTagName("Item");
	var currentRestArrayLength = this.restArray.length;
	if (itemNodes.length == 0) { return; }
	for (var i = 0; i < itemNodes.length; ++i) {
		var name = this.getNodeValue(itemNodes[i], "RestaurantName");
		var url = this.getNodeValue(itemNodes[i], "TabelogUrl");
		var latitude = this.getNodeValue(itemNodes[i], "Latitude");
		var longitude = this.getNodeValue(itemNodes[i], "Longitude");
		var ctg = this.getNodeValue(itemNodes[i], "Category");
		var totalScores = this.getNodeValue(itemNodes[i], "TotalScore");
		var totalScore = 0;
		if (totalScores.length != 0) { totalScore = parseFloat(totalScores[0]); }
		var tasteScore = 0;
		var tasteScores = this.getNodeValue(itemNodes[i], "TasteScore");
		if (tasteScores.length != 0) { tasteScore = parseFloat(tasteScores[0]); }
		var serviceScore = 0;
		var serviceScores = this.getNodeValue(itemNodes[i], "ServiceScore");
		if (serviceScores.length != 0) { serviceScore = parseFloat(serviceScores[0]); }
		var moodScore = 0;
		var moodScores = this.getNodeValue(itemNodes[i], "MoodScore");
		if (moodScores.length != 0) { moodScore = parseFloat(moodScores[0]); }
		
		var dinner = this.getNodeValue(itemNodes[i], "DinnerPrice");
		var lunch = this.getNodeValue(itemNodes[i], "LunchPrice");
		var bushours = this.getNodeValue(itemNodes[i], "BusinessHours");
		var bushour = (bushours.length > 0) ? bushours[0] : "情報なし";
		
		var holidays = this.getNodeValue(itemNodes[i], "Holiday");
		var holiday = (holidays.length > 0) ? holidays[0] : "";

		this.appendCategory(ctg[0], i + currentRestArrayLength);

		this.restArray.push(new restInfo(url[0], name[0], ctg[0], 
			latitude[0], longitude[0], totalScore, tasteScore, serviceScore,
			moodScore, dinner, lunch, bushour, holiday));
	}

}


/**
 * @brief カテゴリを追加します
 * @param[in] ctg 食べログカテゴリ名
 */
tabelogManager.appendCategory = function(ctg, id)
{
	var ctgArray = ctg.split("、");
	for (var i = 0; i < ctgArray.length; ++i) {
		if (this.categoryInfo.categoryItem[ctgArray[i]] == undefined) {
			this.categoryInfo.categoryItem[ctgArray[i]] = new function() { this.highlight = false; }
			this.categoryInfo.categoryItem[ctgArray[i]].ids = new Array();
			//this.categoryInfo.categoryItem[ctgArray[i]].highlight = false;
			this.categoryInfo.totalCount++;
			this.categoryInfo.categoryItem[ctgArray[i]].ids.push(id);
		} else {
			this.categoryInfo.categoryItem[ctgArray[i]].ids.push(id);
		}
	}
}

/**
 * @brief 食べログのエラー情報を表示します
 * @param[in] errNode エラーノード
 */
tabelogManager.showError = function(errNode)
{
	var msgs = this.getNodeValue(errNode, "Message");
	if (msgs[0] = "ItemNotFound") {
		var txt = mainCanvas.findName("RestInfoText");
		if (txt == undefined) { return; }
		txt.setValue("Text", "この周辺には登録されたレストランがありませんでした。");
		txt.setValue("Visibility", "Visible");
		return;
	}
	$(this.forMsgTag).innerHTML = "エラー：" + msgs[0];
}

/**
 * @brief nodeNameで指定した要素の値をArrayで返します
 * @param[in] parentNode 親ノード(DOM)
 * @param[in] nodeName ノード名
 * @return 結果の配列
 */
tabelogManager.getNodeValue = function(parentNode, nodeName)
{
	var nodes = parentNode.getElementsByTagName(nodeName);
	var resultArray = new Array();
	for (var i = 0; i < nodes.length; ++i) {
		if (nodes[i].hasChildNodes() == false) { continue; }
		resultArray.push(nodes[i].firstChild.nodeValue);
	}
	return resultArray;
}

/**
 * @brief 現在の表示設定を基にXAMLを構築します
 * @param[in] offset レストランIDの開始オフセット
 * @return XAML
 */
tabelogManager.createXAML = function(offset)
{
	var endLoop = this.restArray.length;
	var searchCenter = mapCtrl.getLatLongToPixel(this.searchLat, this.searchLon);
	var diffX = Math.round((BLOCKWIDTH/2) - searchCenter.x);
	var diffY = Math.round((BLOCKHEIGHT/2) - searchCenter.y);

	var xamltxt = '<Canvas Visibility="Visible" Name="AppendedCanvas'+ this.currentPage 
	 +'" Canvas.ZIndex="' + (2100 - this.currentPage) + '" >';
	xamltxt += '<Canvas.RenderTransform><TranslateTransform X="' + (-diffX);
	xamltxt += '" Y="' + (-diffY) + '" Name="AppendedCanvasTranslate' 
	+ this.currentPage + '" /></Canvas.RenderTransform>';

	for (var i = offset; i < endLoop; ++i) {
		var pixel = mapCtrl.getLatLongToPixel(this.restArray[i].latitude,
			this.restArray[i].longitude);
		var score = this.restArray[i].totalScore;
		var zIndex = this.totalResult - i;

		xamltxt += '<Canvas Name="Restaurant' + i + '" ';
		//表示設定・・・閾値以下は即非表示、閾値以上ならカテゴリを考慮
		if (this.restArray[i].totalScore < this.threshTotalScore) {
			xamltxt += 'Visibility="Collapsed" ';
		} else {
			if (this.categoryInfo.highlightAllCategory) {
				xamltxt += 'Visibility="Visible" ';
			} else {
				ctgArray = this.restArray[i].category.split("、");
				var visibility="Collapsed";
				for (var j = 0; j < ctgArray.length; ++j) {
					if (this.categoryInfo.categoryItem[ctgArray[j]].highlight) {
						visibility = "Visible";
						break;
					}
				}
				xamltxt += 'Visibility="' + visibility + '" ';
			}
		}
		xamltxt += 'Canvas.Left="' + (Math.round(pixel.x) + diffX) + '" ';
		xamltxt += 'Canvas.Top="' + (Math.round(pixel.y) + diffY) + '" ';
		xamltxt += 'Canvas.ZIndex="' + zIndex + '" ';
		xamltxt += 'MouseEnter="mouseEnterRestaurant" ';
		xamltxt += 'MouseLeftButtonDown="mouseDownRestaurant" ';
		xamltxt += 'MouseLeftButtonUp="mouseUpRestaurant" '
		xamltxt += 'MouseMove="mouseMoveRestaurant" MouseLeave="mouseLeaveRestaurant" >';
	
	/*
		xamltxt += '<Canvas.RenderTransform>';
		xamltxt += '<TranslateTransform X="0" Y="0" Name="RestaurantTranslate' + i + '" />';
		//xamltxt += '<ScaleTransform ScaleX="0.5" ScaleY="0.5" CenterX="24" CenterY="24" />'
		xamltxt += '</Canvas.RenderTransform>';
*/
		if (score >= 4) {
			xamltxt += this.createRestXAMLScore4(score);
		} else if (score == 0) {
			xamltxt += this.createRestXAMLNoEval();
		} else if (score < 3) {
			xamltxt += this.createRestXAMLScoreUnder3(score);
		} else {
			xamltxt += this.createRestXAMLScore3to4(score, 0, 0);
		}

		xamltxt += '<TextBlock FontSize="14" Foreground="Black" Text="' 
		+ Math.floor(score) + '" ';
		xamltxt += 'Canvas.Left="-5" Canvas.Top="-8" />';
		//xamltxt += 'Canvas.ZIndex="' + zIndex + '" ';
		//xamltxt += 'Name="RestText' + i + '" ';
		//xamltxt += 'MouseEnter="mouseEnterToRest" />';

		xamltxt += '</Canvas>';
	}
	xamltxt += "</Canvas>";
	return xamltxt;
}

/**
 * @brief 評価４以上のレストランのXAMLを構築します
 * @param[in] score 評価値
 */
tabelogManager.createRestXAMLScore4 = function(score)
{
	var xamltxt = "";

	xamltxt = '<Polygon Fill="White" Stroke="Black" StrokeThickness="1" ';
	xamltxt += 'Points="0,10 10,10 14,0 17,10 28,10 19,17 22,28 14,21 5,28 8,17" '
	xamltxt += 'Canvas.Top="-13" Canvas.Left="-13" />';
	
	
	xamltxt += '<Polygon Fill="#b0f000" Canvas.Top="-11" Canvas.Left="-11" ';
	xamltxt += 'Points="0,9 9,9 12,0 15,9 24,9 16,15 19,24 12,18 4,24 7,15" >';
	xamltxt += '<Polygon.Clip>';
	var height = Math.round(24 * (score - Math.floor(score)) );
	xamltxt += '<RectangleGeometry Rect="0,' + (24-height) + ',24,' + height +'" />';
	xamltxt += '</Polygon.Clip>';
	xamltxt += '</Polygon>';

	
	return xamltxt;
}

/**
 * @brief 評価３～４のレストランのXAMLを構築します
 * @param[in] score 評価値
 */
tabelogManager.createRestXAMLScore3to4 = function(score)
{
	var xamltxt = "";
	//土台の円
	xamltxt = '<Ellipse Fill="White" Stroke="Black" StrokeThickness="1" Width="20" Height="20" ';
	xamltxt += 'Canvas.Top="-10" Canvas.Left="-10" />';

	//塗りつぶしの円
	xamltxt += '<Ellipse Fill="#00FFFF" Width="18" Height="18" ';
	xamltxt += 'Canvas.Left="-9" Canvas.Top="-9" >';
	xamltxt += '<Ellipse.Clip>';

	var height = Math.round(20 * (score - Math.floor(score)) );
	xamltxt += '<RectangleGeometry Rect="0,' + (20 - height) + ',20,' + height + '" />';
	xamltxt += '</Ellipse.Clip>';

	xamltxt += '</Ellipse>';
	return xamltxt;
}

/**
 * @brief 評価0～2のレストランのXAMLを構築します
 * @param[in] score 評価値
 */
tabelogManager.createRestXAMLScoreUnder3 = function(score)
{
	var xamltxt = "";
	//土台の三角
	xamltxt = '<Polygon Fill="White" Stroke="Black" StrokeThickness="1" Points="0,0 10,21 21,0" ';
	xamltxt += 'Canvas.Top="-8" Canvas.Left="-11" />';

	//塗りつぶしの三角
	xamltxt += '<Polygon Fill="#f0c600" Points="0,0 9,19 19,0" ';
	xamltxt += 'Canvas.Left="-10" Canvas.Top="-7" >';
	xamltxt += '<Polygon.Clip>';

	var height = Math.round(20 * (score - Math.floor(score)) );
	xamltxt += '<RectangleGeometry Rect="0,' + (19 - height) + ',19,' + height + '" />';
	xamltxt += '</Polygon.Clip>';
	
	xamltxt += '</Polygon>';

	return xamltxt;
}

/**
 * @brief 未評価のレストランのXAMLを構築します
 */
tabelogManager.createRestXAMLNoEval = function()
{
	return '<Rectangle Fill="White" Stroke="Black" StrokeThickness="1" Width="18" Height="18" Canvas.Left="-9" Canvas.Top="-9" />';
}

/**
 * @brief レストランの表示・非表示を切り替えます
 * @param[in] slObj Silverlightオブジェクト
 * @param[in] isShow 表示/非表示のフラグ
 */
tabelogManager.showRestaurant = function(slObj, isShow)
{
	for (var i = 1; i <= this.currentPage; ++i) {
		var appCanvas = slObj.findName("AppendedCanvas" + i);
		if (appCanvas != undefined) {
			if (isShow) {
				appCanvas.setValue("Visibility", "Visible");
			} else {
				appCanvas.setValue("Visibility", "Collapsed");
			}
		}
	}
}

/**
 * @brief レストラン座標を再配置します（完全再計算のため重い）
 * @param[in] slObj silverlightオブジェクト
 */
tabelogManager.replotRestaurant = function(slObj)
{
	var count = 0;
	var searchCenter = mapCtrl.getLatLongToPixel(this.searchLat, this.searchLon);
	var diffX = Math.round((BLOCKWIDTH/2) - searchCenter.x);
	var diffY = Math.round((BLOCKHEIGHT/2) - searchCenter.y);
	for (var i = 1; i <= this.currentPage; ++i) {
		var canvasObj = slObj.findName("AppendedCanvas" + i);
		if (canvasObj == undefined) { continue; }
		var transObj = canvasObj.getValue("RenderTransform");
		transObj.setValue("X", -diffX);
		transObj.setValue("Y", -diffY);
		for (var j = 0; j < canvasObj.children.count; ++j) {
			var restObj = canvasObj.children.getItem(j);
			if (restObj == undefined) { continue; }
			var pixel = mapCtrl.getLatLongToPixel(this.restArray[count].latitude,
				this.restArray[count].longitude);
			restObj.setValue("Canvas.Left", Math.round(pixel.x) + diffX);
			restObj.setValue("Canvas.Top", Math.round(pixel.y) + diffY);
			++count;
		}
	}
}

/**
 * @brief レストラン座標を中心座標のズレから再配置します(平行移動時に使用)
 * @param[in] slObj Silverlightオブジェクト
 */
tabelogManager.replotRestaurantLite = function(slObj)
{
	var searchCenter = mapCtrl.getLatLongToPixel(this.searchLat, this.searchLon);
	var diffX = Math.round((BLOCKWIDTH/2) - searchCenter.x);
	var diffY = Math.round((BLOCKHEIGHT/2) - searchCenter.y);
	for (var i = 1; i < this.currentPage; ++i) {
		var transObj = slObj.findName("AppendedCanvasTranslate" + i);
		if (transObj == undefined) { continue; }
		transObj.setValue("X", -diffX);
		transObj.setValue("Y", -diffY);
	}
	//slObj.findName("RestInfoText").setValue("Text", "(" + diffX + ", " + diffY + ")");
}

/**
 * @brief カテゴリのXAMLを作成します
 * @param[in] page 表示ページ(1-based)
 */
tabelogManager.createCategorySelectXAML = function(page)
{
	var xamltxt = '<Canvas Background="#cdffffff" Canvas.Left="380" Canvas.Top="20" Width="240" Height="440" Canvas.ZIndex="3000" >';

	xamltxt += '<TextBlock FontSize="12" Canvas.Top="2" Canvas.Left="10" Text="全レストランを表示" Name="ShowAllCategory" MouseLeftButtonDown="clickAllCategory" ';
	if (this.categoryInfo.highlightAllCategory) {
		xamltxt += 'Foreground="Red" ';
	} else {
		xamltxt += 'Foreground="Black" ';
	}
	xamltxt += 'MouseEnter="mouseEnterCategory" MouseLeave="mouseLeaveCategory" Cursor="Hand" />';
	xamltxt += '<Line Canvas.Top="20" Canvas.Left="2" Stroke="Black" StrokeThickness="1" X1="0" Y1="0" X2="235" Y2="0" />';

	var top = 22;
	var startOffset = 20 * (page-1);
	var loopCount = -1;
	for (var prop in this.categoryInfo.categoryItem) {
		++loopCount;
		if (loopCount < startOffset) { continue; }
		xamltxt += '<TextBlock FontSize="12" Canvas.Left="10" Canvas.Top="' + top + '" ';
		xamltxt += 'Text="' + prop + ' (' + this.categoryInfo.categoryItem[prop].ids.length + ')" ';
		if (this.categoryInfo.categoryItem[prop].highlight) {
			xamltxt += 'Foreground="Red" ';
		} else {
			xamltxt += 'Foreground="Black" ';
		}
		xamltxt += 'Cursor="Hand" ';
		xamltxt += 'Name="' + prop + '" ';
		xamltxt += 'MouseLeftButtonDown="clickCategory" '; //silverlightControl.jsに記述
		xamltxt += 'MouseEnter="mouseEnterCategory" '; //同上
		xamltxt += 'MouseLeave="mouseLeaveCategory" />'; //同上
		top += 20;
		if (top >= 420) { break; }
	}
	xamltxt += '<Line Canvas.Top="420" Canvas.Left="2" Stroke="Black" StrokeThickness="1" X1="0" Y1="0" X2="235" Y2="0" />';

	var endLoop = Math.ceil(this.categoryInfo.totalCount / 20);
	if (endLoop > 0) {
		xamltxt += '<TextBlock FontSize="12" Canvas.Top="422" Canvas.Left="10" Text="Page" />';
		xamltxt += '<Rectangle Width="12" Height="16" IsHitTestVisible="False" Fill="#20ff0000" Canvas.Top="422" Canvas.Left="-30" Visibility="Collapsed" Name="CategoryPageFocus" />';
		xamltxt += '<Rectangle Width="12" Height="16" IsHitTestVisible="False" Stroke="#ff0000" StrokeThickness="1" Canvas.Top="422" Canvas.Left="' + ((page-1)*16 + 46) + '" />';
	}
	for (var i = 0; i < endLoop; ++i) {
		xamltxt += '<TextBlock FontSize="12" Canvas.Top="422" Canvas.Left="' + (48+(i*16)) + '" ';
		xamltxt += 'Text="' + (i+1) + '" Name="CategoryPage' + (i+1) +'" ';
		xamltxt += 'Cursor="Hand" TextDecorations="Underline" MouseEnter="mouseEnterCategoryPage" ';
		xamltxt += 'MouseLeave="mouseLeaveCategoryPage" MouseLeftButtonDown="clickCategoryPage" />';
	}
	xamltxt += '</Canvas>';
	return xamltxt;
}

/**
 * @brief 全てのレストランを一括して表示/非表示にします
 * @param[in] slObj Silverlightオブジェクト
 * @param[in] isVisible 表示するかどうか
 * @param[in] isEvalThresh 閾値を考慮するか否か
 */
tabelogManager.showAllRestaurant= function(slObj, isVisible, isEvalThresh)
{
	var visibility = (isVisible) ? "Visible" : "Collapsed";
	for (var i = 0; i < this.restArray.length; ++i) {
		var obj = slObj.findName("Restaurant" + i);
		if (obj != undefined) {
			if (!isEvalThresh) {
				obj.setValue("Visibility", visibility);
			} else {
				if (this.restArray[i].totalScore < this.threshTotalScore) {
					obj.setValue("Visibility", "Collapsed");
				} else {
					obj.setValue("Visibility", visibility);
				}
			}
		}
	}
}

/**
 * @brief カテゴリ選択変更時の処理を行います
 * @param[in] slObj Silverlightオブジェクト
 * @param[in] name カテゴリ名
 * @param[in] isVisible 表示するかどうか
 */
tabelogManager.changeCategorySelection = function(slObj, name, isVisible)
{
	var alCate = slObj.findName("ShowAllCategory");
	var brush = alCate.getValue("Foreground");
	var color = brush.getValue("Color");
	if ((color & 0xffffff) != 0) {
		this.showAllRestaurant(slObj, false, true);
		brush.setValue("Color", "Black");
		this.categoryInfo.highlightAllCategory = false;
	}

	var ar = this.categoryInfo.categoryItem[name].ids;
	if (ar == undefined) { return; }
	var visibility = (isVisible) ? "Visible" : "Collapsed";
	for (var i = 0; i < ar.length; ++i) {
		var obj = slObj.findName("Restaurant" + ar[i]);
		if (obj == undefined) { continue; }
		if (this.restArray[ar[i]].totalScore < this.threshTotalScore) {
			obj.setValue("Visibility", "Collapsed");
			continue;
		}
		var ctgArray = this.restArray[ar[i]].category.split("、");
		var isIgnore = false;
		for (var j = 0; j < ctgArray.length; ++j) {
			if (this.categoryInfo.categoryItem[ctgArray[j]].highlight) {
				if (ctgArray[j] == name) { continue; }
				isIgnore = true;
				break;
			}
		}
		if (isIgnore) { continue; }
		obj.setValue("Visibility", visibility);
	}

	this.categoryInfo.categoryItem[name].highlight = isVisible;
}

/**
 * @brief Z-Orderを反転します
 * @param[in] slObj Silverlightオブジェクト
 */
tabelogManager.reverseZOrder = function(slObj)
{
	for (var i = 1; i <= this.currentPage; ++i) {
		var obj = slObj.findName("AppendedCanvas" + i);
		if (obj == undefined) { continue; }
		var zid = 4100 - parseInt(obj.getValue("Canvas.ZIndex"));
		obj.setValue("Canvas.ZIndex", zid);

		for (var j = 0; j < obj.children.count; ++j) {
			var childObj = obj.children.getItem(j);
			if (childObj == undefined) { continue; }
			var childZid = this.totalResult - parseInt(childObj.getValue("Canvas.ZIndex"));
			childObj.setValue("Canvas.ZIndex", childZid);
		}
	}
}

/**
 * @brief 検索範囲を表示します
 */
tabelogManager.showSearchRange = function(slObj, isVisible)
{
	var obj = slObj.findName("searchRange");
	if (!isVisible) {
		obj.setValue("Visibility", "Collapsed");
		return;
	}

	if (this.searchLat == 0 || this.searchLon == 0) { return; }

	this.resizeSearchRangeAnother(obj, this.searchedRange);
	obj.setValue("Visibility", "Visible");
}

/**
 * @brief 検索範囲のリサイズを行います。
 * @param[out] slObj Silverlightオブジェクト
 * @param[in] rangeId 検索範囲ID
 */
tabelogManager.resizeSearchRange = function(slObj, rangeId)
{
	var latLong = mapCtrl.getPixelToLatLong(0,0);
	var addLat = 0;
	var addLon = 0;
	if (rangeId == RANGE_SMALL) {
		addLat = 0.0014; addLon = 0.0028;
	} else if (rangeId == RANGE_MEDIUM) {
		addLat = 0.00333; addLon = 0.00661;
	} else if (rangeId == RANGE_LARGE) {
		addLat = 0.00694; addLon = 0.0125;
	} else{
		return;
	}
	var pLat = mapCtrl.getLatLongToPixel(latLong.Latitude + addLat, latLong.Longitude);
	var pLng = mapCtrl.getLatLongToPixel(latLong.Latitude, latLong.Longitude + addLon);
	var rangeW = Math.round(Math.abs(pLng.x));
	var rangeH = Math.round(Math.abs(pLat.y));
	slObj.setValue("Width", rangeW * 2);
	slObj.setValue("Height", rangeH * 2);
}

tabelogManager.resizeSearchRangeAnother = function(slObj, rangeId)
{
	var latLong = mapCtrl.getPixelToLatLong(0,0);
	var addLat = 0;
	var addLon = 0;
	if (rangeId == RANGE_SMALL) {
		addLat = 0.0014; addLon = 0.0028;
	} else if (rangeId == RANGE_MEDIUM) {
		addLat = 0.00333; addLon = 0.00661;
	} else if (rangeId == RANGE_LARGE) {
		addLat = 0.00694; addLon = 0.0125;
	} else{
		return;
	}
	var pLat = mapCtrl.getLatLongToPixel(latLong.Latitude + addLat, latLong.Longitude);
	var pLng = mapCtrl.getLatLongToPixel(latLong.Latitude, latLong.Longitude + addLon);
	var rangeW = Math.round(Math.abs(pLng.x)) * 2;
	var rangeH = Math.round(Math.abs(pLat.y)) * 2;
	var points = "0,0 " + rangeW + ",0 " + rangeW + "," + rangeH + " 0," + rangeH + " 0,0";
	slObj.setValue("Points", points);
	var centerPix = mapCtrl.getLatLongToPixel(this.searchLat, this.searchLon);
	slObj.setValue("Canvas.Left", centerPix.x - (rangeW/2));
	slObj.setValue("Canvas.Top", centerPix.y - (rangeH/2));
}

/**
 * @brief 検索範囲を移動します
 * @param[out] slObj 移動する検索範囲Silverlightオブジェクト
 * @param[in] x 検索範囲の中心x
 * @param[in] y 検索範囲の中心y
 */
tabelogManager.moveSearchRange = function(slObj, x, y)
{
	var w = parseInt(slObj.getValue("Width")) / 2;
	var h = parseInt(slObj.getValue("Height")) / 2;
	slObj.setValue("Canvas.Left", x - w);
	slObj.setValue("Canvas.Top", y - h);
}

/**
 * @brief 評価閾値設定し、アイコンに反映します
 * @param[in] thresh 閾値
 * @param[in] slObj Silverlightオブジェクト
 */
tabelogManager.setTotalThresh = function(thresh, slObj)
{
	var oldThresh = this.threshTotalScore;
	this.threshTotalScore = thresh;
	if (this.restArray.length == 0) { return; }

	var endLoop = this.restArray.length;
	var id1 = endLoop - 1;
	var id2 = endLoop - 1;
	for (var id = 0; id < endLoop; ++id) {
		if ((id1 == endLoop - 1) && (this.restArray[id].totalScore < oldThresh)) {
			id1 = id;
			if (id2 != endLoop - 1) { break; }
		}
		if ((id2 == endLoop - 1) && (this.restArray[id].totalScore < thresh)) {
			id2 = id;
			if (id1 != endLoop - 1) { break; }
		}
	}
	
	if (id1 == id2) { //同値の場合
		if (this.restArray[id1].totalScore < thresh) {
			slObj.findName("Restaurant" + id1).setValue("Visibility", "Collapsed");
		} else {
			if (this.categoryInfo.highlightAllCategory) {
				slObj.findName("Restaurant" + id1).setValue("Visibility", "Visible");
			} else {
				ctgArray = this.restArray[id1].category.split("、");
				for (var j = 0; j < ctgArray.length; ++j) {
					if (this.categoryInfo.categoryItem[ctgArray[j]].highlight) {
						slObj.findName("Restaurant" + id1).setValue("Visibility", "Visible");
						break;
					}
				}
			}
		}
		return;
	}
	
	var visibility = (thresh > oldThresh) ? "Collapsed" : "Visible";
	var diff = (id1 > id2) ? -1 : 1;
	var cond = (id1 > id2) 
	 ? function(i, id2) { return (i >= id2); } : function(i, id2) { return (i < id2); };
	if ((thresh > oldThresh) || (this.categoryInfo.highlightAllCategory)) {
		for (var id = id1; cond(id, id2); id += diff) {
			slObj.findName("Restaurant" + id).setValue("Visibility", visibility);
		}
	} else {
		for (var id = id1; cond(id, id2); id += diff) {
			ctgArray = this.restArray[id].category.split("、");
			for (var j = 0; j < ctgArray.length; ++j) {
				if (this.categoryInfo.categoryItem[ctgArray[j]].highlight) {
					slObj.findName("Restaurant" + id).setValue("Visibility", "Visible");
					break;
				}
			}
		}
	}
}

/**
 * @brief 検索範囲を設定します
 * @param[in] rangeId サーチレンジID
 */
tabelogManager.setSearchRange = function(rangeId)
{
	this.searchRange = rangeId;
}
