var mc;	// map controller

/**
 * Mapコントローラ。すべての地図への操作はすべてこのインターフェースを通して
 * 行う。
 */
SJP.MapController = function( map, element ) {
	this.map_ = map;
	this.locations_ = new Array();
	this.groupedLocation_ = {};
	this.activeGroup = {};

	for ( var i = 0; i < SERVICES.length; i++ ) {
		this.activeGroup[SERVICES[i]] = true;
	}

	this.reporter_;

	if ( element ) {
		element = document.getElementById(element);
		this.htmlMan_ = new SJP.HtmlManager( element );
	};
};

SJP.MapController.prototype.setMaxNum = function(n) {
	this.maxNum = n;
	// 今まで利用していたreporterクラスを無効にする。
	if ( this.reporter_ ) {
		this.reporter_.purge();
	}
	this.reporter_ = new SJP.Reporter(this.maxNum);
};

/**
 * コンビニ情報の追加を行う。
 * <p>コンビニ情報を引数として与える。メソッドはコンビニ情報を元に、新規の地点情報を作成し、管理する。</p>
 * @param data コンビニ情報
 * @return このメソッドは何も返さない。
 */
SJP.MapController.prototype.addLocation = function( data, gid ) {
	var me = this;

	// 持ち込み情報が存在しない場合、無視する。
	var sm = SERVICE_MAP( data.i );
	if ( sm == null || sm.length == 0 ) {
		me.reporter_.skip();
		return;
	};

	var newLocation;

	// 拠点番号から対応サービスを取得し、アクティブリストと比較し、オプションを生成する。
	var services = SERVICE_MAP( data.i );
	var hide = true;

	for ( var i = 0; i < services.length ; i++ ) {
		for ( var item in me.activeGroup ) {
			if ( services[i] == item ) {
				hide = false;
			}
		}
	}

	(function(r){
		newLocation = new SJP.Location( me.map_, data, gid, {
				onLoad:function(){r.add();},
				hidden:hide
			});
		}
	)(me.reporter_);

	me.locations_[this.locations_.length] = newLocation;

	for ( var d = 0; d < gid.length ; d++ ) {
		var id = "" + gid[d];
		// グループ別のLocationを登録する。
		if ( me.groupedLocation_[id] == undefined ) {
			me.groupedLocation_[id] = new Array();
		}
		me.groupedLocation_[id][me.groupedLocation_[id].length] = newLocation;
	};
	// マーカークリック時の動作を設定する。
	(function(loc,iid){
		loc.onMarkerClick = function() {
				me.select(iid);
			};
		}
	)( newLocation, this.locations_.length );

	if ( this.htmlMan_ ) {
		this.htmlMan_.addLocation( newLocation, hide );
	}

};

/**
 * グループ化されたIDを表示させる。
 * @param gid グループID
 * @return 成功時:true, 失敗時:false
 */
SJP.MapController.prototype.showGroup = function( gid ) {
	var me = this;

	gid = "" + gid;

	// グループIDが設定されている場合に全てのLocationにshowメッセージを送る。
	if ( me.groupedLocation_[gid] == undefined ) {
		return false;
	}
	for ( var i = 0; i < me.groupedLocation_[gid].length; i++ ) {
		me.groupedLocation_[gid][i].show();
		if ( me.groupedLocation_[gid][i]._hm_count_id ) {
			me.htmlMan_.show( me.groupedLocation_[gid][i]._hm_count_id );
		}
	}

	me.activeGroup[gid] = true;

	return true;
};

/**
 * グループ化されたIDを非表示にする。
 * @param gid グループID
 * @return
 */
SJP.MapController.prototype.hideGroup = function( gid ) {
	var me = this;

	var id = "" + gid;

	delete me.activeGroup[id];

	// グループIDが設定されているLocationからグループ番号を取得し
	// そのグループが非表示の場合に、非表示にする。
	if ( me.groupedLocation_[id] == undefined ) {
		return false;
	}

	var locationList = me.groupedLocation_[id];

	// Location毎の処理
	for ( var i = 0; i < locationList.length; i++ ) {
		var location = locationList[i];

		var glist = location.getGroupList();
		var wantAlive = false;
		for ( var j = 0; j < glist.length; j++ ) {
			for ( var item in me.activeGroup ) {
				if ( glist[j] == item ) {
					wantAlive = true;
				}
			}
		}
		if ( !wantAlive ) {
			location.hide();
			if ( location._hm_count_id ) {
				me.htmlMan_.hide( location._hm_count_id );
			}
		}
	}

	return true;
};

/**
 * 全てのLocationオブジェクトにterminate(終了)メッセージを送り、地図、表示上から削除する。
 * 内部の変数もすべてリセットする。
 * 但し、activeGroupについては、初期化を行わない。
 * @return
 */
SJP.MapController.prototype.reset = function() {
	var me = this;
	for ( var i = 0; i < me.locations_.length; i++ ) {
		me.locations_[i].terminate();
	}
	me.locations_ = new Array();
	me.groupedLocation_ = {};
	if ( this.htmlMan_ ) {
		this.htmlMan_.clear();
	}
};

SJP.MapController.prototype.select = function(id) {
	var me = this;
	if ( !me.locations_[id-1] ) {
		return;
	}
	me.locations_[id-1].select();
	if ( this.htmlMan_ ) {
		this.htmlMan_.select( id );
	}
};

SJP.MapController.prototype.setMapCenter = function( lat, lng ) {
	if ( lat == undefined && lng == undefined ) {
		return;
	}

	var me = this;
	me.map_.setCenter( new GLatLng( lat, lng ), 13 );
};

SJP.MapController.prototype.setMapCenterByAddress = function( address ) {
	if ( address == undefined ) {
		return;
	}

	var me = this;
	// Google Maps Geocoder を Location の静的変数から拝借する。
	var cache = SJP.Location.gcache ? SJP.Location.gcache : new GClientGeocoder();

	(function(adrs, me_){
		cache.getLatLng( adrs, function( coord ) {
			if ( coord && address == adrs ) {	// ちょっとしたトリック： スコープ内の値と外の値が一致する場合(他の呼び出しがない)にのみ、動作する。
				try {
					me_.setCenter( coord.lat(), coord.lng() );
				} catch ( e ) {
					alert( "住所の取得を行うことができませんでした。" );
					var img = new Image(1,1);
					img.src = "/images/dummy.gif?error=" + escape(e.toString());
				}
			}
		} );
	})(address, me);
};

/**
 * HTMLマネージャ
 * @param node HTMLノード
 */
SJP.HtmlManager = function( node ) {
	this.node_ = node;
	this.count = 0;
	this.activeNode = null;
	this.locationNodes = new Array();
};

SJP.HtmlManager.prototype.addLocation = function( location, hidden ) {
	if ( !this.node_ ) {
		return;
	}

	this.count++;

	var cls = this.count % 2 == 0 ? 'even' : 'odd' ;

	var child = document.createElement("li");
//	var center_name = SJP.CENTER_NAMES(location.data_.i);
	var center_name = location.data_.n;
	var service_names = (function(c) {
		var list = SERVICE_MAP(c);
		var names = new Array();
		for ( var i = 0; i < list.length; i++ ) {
			names[names.length] = SJP.SERVICE_NAMES[ list[i] ];
		}
		if ( names.length > 0 ) {
			return names.join(", ");
		} else {
			return "";
		}
	})(location.data_.i);
	
	child.innerHTML = '<div class="center_icon"><a href="javascript:void(0);" onclick="mc.select('+this.count+');"><img src="images/stand_' + location.data_.i + '.png" /></a></div><div class="center_summary"><h3><a href="javascript:void(0);" onclick="mc.select('+this.count+');">'+center_name+'</a></h3><p>'+service_names+'</p></div>';
	child.className = cls;
	child.id = "MCITEM-" + this.count;
	if (hidden)
		child.style.display = "none";

	this.node_.appendChild( child );

	this.locationNodes[this.locationNodes.length] = child;

	location.htmlElement_ = child;
	location._hm_count_id = this.count;
};

SJP.HtmlManager.prototype.hide = function(id) {
	if ( this.locationNodes[id-1] == undefined ) {
		return;
	}
	this.locationNodes[id-1].style.display = "none";
};

SJP.HtmlManager.prototype.show = function(id) {
	if ( this.locationNodes[id-1] == undefined ) {
		return;
	}
	this.locationNodes[id-1].style.display = "list-item";
};

SJP.HtmlManager.prototype.select = function(id) {
	var me = this;
	if ( me.activeNode ) {
		var cls = me.activeNode.className;
		var classes = cls.split(" ");
		var newcls = new Array();
		for ( var i = 0; i < classes.length; i++ ) {
			if ( classes[i] != "mcactive" ) {
				newcls[newcls.length] = classes[i];
			}
		};
		if ( newcls.length > 0 ) {
			me.activeNode.className = newcls.join(" ");
		} else {
			me.activeNode.className = null;
		}
	}
	var newnode = document.getElementById( "MCITEM-" + id );
	if ( newnode == null ) {
		return;
	}
	if ( newnode.className && newnode.className.indexOf("mcactive") < 0 ) {
		newnode.className = newnode.className + " mcactive";
	} else {
		newnode.className = "mcactive";
	}
//	newnode.prevstyle = newnode.style;
//	newnode.style.backgroundColor = "#fcc";
	me.activeNode = newnode;
};

SJP.HtmlManager.prototype.clear = function() {
	var me = this;
	if (me.activeNode) {
		me.activeNode == null;
	}
	while ( this.node_.childNodes.length > 0 ) {
		this.node_.removeChild( this.node_.firstChild );
	}
	me.count = 0;
	me.locationNodes = new Array();
};

/**
 * 位置情報オブジェクト
 * @param map Google Maps API インスタンス
 * @param data 位置情報データ
 * @param gid グループID
 * @param options オプション
 */
SJP.Location = function( map, data, gid, options ){
	var me = this;
	
	this.map_ = map;
	this.data_ = data;
	this.groups = gid;
	this.marker_ = null;

	if ( options && options.onLoad ) {
		this.onLoad = options.onLoad;
	};

	if ( options && options.hidden ) {
		this.hidden = true;
	} else {
		this.hidden = false;
	};
	
	// 非表示フラグが立っていない場合、地図への表示を行う。
	if ( options && data.lt && data.lg ) {
		me.addOverlay_();
		if ( me.onLoad )
			me.onLoad();
	} else {
		var cache = SJP.Location.gcache ? SJP.Location.gcache : new GClientGeocoder();
		if ( SJP.Location.gcache == undefined ) {
			SJP.Location.gcache = cache;
		}

		var executer = SJP.Location.executer ? SJP.Location.executer : new SerialExecuter( 2 );
		if ( SJP.Location.executer == undefined ) {
			SJP.Location.executer = executer;
		}

		(function(me_,cache_,exec_) {
			var me__ = me_;
			var cache__ = cache_;
			var exec = function() {
				this.execute = function() {
					cache__.getLatLng( me_.data_.an, this.callback );
				};
				this.callback = function( address ) {
					if ( me__.onLoad ) {
						me__.onLoad();
					}
					if ( address != null ) {
						me__.locate_( address );
					}
				};
			};
			exec_.execute( new exec() );
		})(me,cache,executer);
	};

};

/**
 * Locationオブジェクトの位置を設定する。
 * @param address GLatLngオブジェクト
 * @return
 */
SJP.Location.prototype.locate_ = function( address ) {
	var me = this;
	if ( address == undefined )
		return;

	me.data_.lt = address.lat();
	me.data_.lg = address.lng();
	me.addOverlay_();
};

/**
 * 地図上への表示を行う。
 * @return
 */
SJP.Location.prototype.addOverlay_ = function() {
	var me = this;
	if ( me.map_ == undefined || me.data_ == undefined || me.data_.lt == undefined ) {
		return false;
	};

	// 表示しないフラグが設定されている場合、表示を行わない。
	if ( me.hidden ) {
		return true;
	};

	// アイコンの作成　( 定義されていない場合に、定義を行う )
	if ( me.marker_ == null ) {
		var icon = create_GIcon_D( me.data_.i );
		try {
			me.marker_ = new GMarker( new GLatLng( me.data_.lt, me.data_.lg ), icon );
			GEvent.addListener(
					me.marker_,
					"click",
					function() {
						if (me.onMarkerClick) {
							me.onMarkerClick();
						}
					}
			);
		} catch ( e ) {
			return false;
		}
	}

	me.map_.addOverlay( me.marker_ );

	return true;
};

/**
 * 終了処理を行う。
 * @return
 */
SJP.Location.prototype.terminate = function() {
	var me = this;
	me.hide();
};

/**
 * Locationを非表示にする。
 * @return
 */
SJP.Location.prototype.hide = function() {
	var me = this;
	me.hidden = true;
	if ( me.marker_ != null ) {
		me.map_.removeOverlay( me.marker_ );
	}
};

/**
 * Locationを表示する。
 * @return
 */
SJP.Location.prototype.show = function() {
	var me = this;
	me.hidden = false;
	me.addOverlay_( me.marker_ );
};

SJP.Location.prototype.select = function() {
	var me = this;
	// 地図のHTMLウィンドウを開く。
	if (me.marker_)
		me.marker_.openInfoWindowHtml( SJP.template.format( me.data_ ) );
};

SJP.Location.prototype.onLoad = function() {
};

SJP.Location.prototype.getGroupList = function() {
	return SERVICE_MAP( this.data_.i );
};


SJP.Reporter = function(ttl) {
	this.total = ttl;
	this.progress = progress = new JS_BRAMUS.jsProgressBar($('progress_bar'),0,{animate: false, showText: false});
;
	this.count = 0;
	this.disabled = false;
};
SJP.Reporter.prototype.add = function(){
	if ( this.disabled ) return;
	this.count++;
	this.render();
};
SJP.Reporter.prototype.pass = function(){
	if ( this.disabled ) return;
	this.count++;
	this.render();
};
SJP.Reporter.prototype.skip = function(){
	if ( this.disabled ) return;
	this.count++;
	this.render();
};
SJP.Reporter.prototype.purge = function(){
	if ( this.disabled ) return;
	this.disabled = true;
	this.render();
};
SJP.Reporter.prototype.render = function() {
	if ( this.progress ) {
		this.progress.setPercentage( this.count / this.total * 100 + "" );
	}
};

function create_GIcon_D ( type ) {
	try {
		if ( SJP.GIcons_D[ type + "" ] ) {
			return SJP.GIcons_D[ type + "" ];
		} else {
			return SJP.GIcons_D[ 0 ];
		}
	} catch ( e ) {
		alert( e );
	}
	return null;
};

function load_apis () {
	var modules = [
			"/js/autosuggest_2.1.3/src.js",
			"/js/prototypejs_1.6/src.js",
			"/js/bramus/jsProgressBarHandler.js",
			"./SerialExecuter.js"
			];
	
	document.open();
	for ( var i = 0; i < modules.length; i++ ) {
		document.write('<script type="text/javascript" charset="utf-8" src="' + modules[i] + '"></script>');
	}
	document.close();

	return true;
};

var progress;

/**
 * JavaScriptアプリケーションの初期化を行う。
 * @return
 */
function init () {
	if (GBrowserIsCompatible()) {
		var map = new GMap2(document.getElementById("map_canvas"));
		map.setCenter(new GLatLng(36.597889, 137.988281), 4);
		map.disableDoubleClickZoom();
		map.addControl( new GLargeMapControl3D() );

		mc = new SJP.MapController( map, "list" );
	}


	progress = new JS_BRAMUS.jsProgressBar(
					$('progress_bar'),
					0,
					{animate: false, showText: false}
				);

	var options = {
		script: "/mochi-komi/postal.cgi?",
		varname: "v",
		maxentries: 10,
		cache: false,
		timeout: 10000,
		noresults: "郵便番号が見つかりません"
	};
	var as = new bsn.AutoSuggest('postal', options);

	SJP.GIcons = [];
	SJP.GIcons_D = [];
	
	var nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,15,101,151,161,162,171];

	for ( var i = 0; i < nums.length; i++ ) {
		SJP.GIcons_D[ nums[i] + "" ] = new GIcon();
		SJP.GIcons_D[ nums[i] + "" ].iconSize = new GSize(18,22);
		SJP.GIcons_D[ nums[i] + "" ].shadowSize = new GSize(30,22);
		SJP.GIcons_D[ nums[i] + "" ].iconAnchor = new GPoint(10,24);
		SJP.GIcons_D[ nums[i] + "" ].infoWindowAnchor = new GPoint(9,0);
		SJP.GIcons_D[ nums[i] + "" ].image = "images/stand_" + nums[i] + ".png";
		SJP.GIcons_D[ nums[i] + "" ].shadow = "images/stand_shadow.png";
	}
};

/**
 * 郵便番号の検索を行い、結果を表示するオブジェクト
 * @param code 郵便番号
 * @return
 */
function search( code ) {

	code = escape(code);

	mc.reset();

	var ajx = new Ajax.Request(
			'/mochi-komi/handin_point.cgi',
			{
				method: 'get',
				parameters: 'pc=' + code,
				onComplete: reload_stations
			}
		);
};

function deffered_search ( code ) {

	code = escape(code);
	
	var ajx = new Ajax.Request(
			'/mochi-komi/handin_point.cgi',
			{
				method: 'get',
				parameters: 'pc=' + code,
				onComplete: function(d) {
					mc.reset();
					reload_stations(d);
				}
			}
		);
};

/**
 * AJAX 呼び出しのコールバック関数。コンビニデータのテキストデータを引数にとる。
 * @param originalRequest コンビニデータのテキストデータ(JSON形式)
 * @return なし
 */
function reload_stations (originalRequest) {
	var data = originalRequest.responseText.evalJSON();

	var location_list = data.data;

	// 住所の表示を行う。
	document.getElementById("progress_text").innerHTML = data.address ? "住所: <b>" + data.address + "</b>" : "住所が見つかりません";

	// 地図の現在地を設定する。
	// 座標がある場合は座標により、座標がない場合は住所で中心点を設定する。
	if ( data.address_coord ) {
		mc.setMapCenter(data.address_coord.lat, data.address_coord.lng);
	} else {
		mc.setMapCenterByAddress(data.address);
	}

	mc.setMaxNum(location_list.length);
	DataPicker.reset();
	for ( var i = 0; i < location_list.length; i++ ) {
		var grouplist = SERVICE_MAP(location_list[i].i);
		mc.addLocation(location_list[i], grouplist);

		for ( var j = 0; j < grouplist.length; j++ ) {
			DataPicker.add( grouplist[j] );
		}
	
	}

	DataPicker.show();
}

function toggleService (name, elm) {
	var _selected_num = 0;
/*	for ( var i = 0; i < SERVICES.length; i++ ) {
		var e = document.getElementById(SERVICES[i]);
		if ( e.checked ) {
			_selected_num++;
		}
	}*/

	if ( elm.checked ) {
/*		for ( var i = 0; i < SERVICES.length; i++ ) {
			var e = document.getElementById(SERVICES[i]);
			e.disabled = false;
		}*/
		mc.showGroup( name );
	} else {
		mc.hideGroup( name );
		// 最後の一個の場合、残ったやつをdisabledにする。
/*		if ( _selected_num == 1 ) {
			for ( var i = 0; i < SERVICES.length; i++ ) {
				var e = document.getElementById(SERVICES[i]);
				if ( e.checked ) {
					e.disabled = true;
				}
			}
		}*/
	}
};

var DataPicker = new function() {
	var node = {};
	this.add = function( item ) {
		if ( node[item] == undefined ) {
			node[item] = 1;
		} else {
			node[item]++;
		}
	};
	this.reset = function() {
		node = {};
		document.getElementById("num-teikeigai").innerHTML = "-";
		document.getElementById("num-youpack").innerHTML = "-";
		document.getElementById("num-takkyubin").innerHTML = "-";
		document.getElementById("num-kuronekomail").innerHTML = "-";
		document.getElementById("num-hikyakubin").innerHTML = "-";
	};
	this.show = function() {
		document.getElementById("num-teikeigai").innerHTML = node["teikeigai"] ? node["teikeigai"] : 0;
		document.getElementById("num-youpack").innerHTML = node["youpack"] ? node["youpack"] : 0;
		document.getElementById("num-takkyubin").innerHTML = node["takkyubin"] ? node["takkyubin"] : 0;
		document.getElementById("num-kuronekomail").innerHTML = node["kuronekomail"] ? node["kuronekomail"] : 0;
		document.getElementById("num-hikyakubin").innerHTML = node["hikyakubin"] ? node["hikyakubin"] : 0;
	};
};


