var mf;
if( !mf ) mf = {};

/***************************
* カレンダー操作モジュール
* 
* @author		Yoshizaki Taiko
* @copyright	Copyright(c) 2009 Yoshizaki Taiko
* @version		0.0.1, Rev.2009-02-06
****************************/
/*****************************************************************************
* カレンダーの作成
* 書式：  mf.Calendar( string tag_id[, object obj_prm] );
*
* @param    tag_id				カレンダーを作るタグのID名
* @param    obj_prm.date		日付オブジェクト　省略したら今月
* @param    obj_prm.past		表示したい過去の月数　省略したら表示なし
* @param    obj_prm.future		表示したい未来の月数　省略したら表示なし
* @param    obj_prm.title		タイトル　省略したら"Calendar"
* @param    obj_prm.user		ユーザID　省略したらリンクなし
*****************************************************************************/
mf.Calendar = function(tag_id, obj_prm) {
	
	mf.Calendar.list[tag_id] = new mf.Calendar2(tag_id, obj_prm);
}

mf.Calendar.list = {};

mf.Calendar.lastMonth = function(tag_id) {
	mf.Calendar.list[tag_id].change(0,-1);
}

mf.Calendar.nextMonth = function(tag_id) {
	mf.Calendar.list[tag_id].change(0,1);
}

mf.Calendar.lastYear = function(tag_id) {
	mf.Calendar.list[tag_id].change(-1,0);
}

mf.Calendar.nextYear = function(tag_id) {
	mf.Calendar.list[tag_id].change(1,0);
}

//カレンダーを初期設定日にする
mf.Calendar.goToday = function(tag_id) {
	mf.Calendar.list[tag_id].setCalendar();
}

mf.Calendar.alt = null;
	
mf.Calendar.date_mouseover = function(obj_a,str_chg)
{
//	alert(list_nodes(obj_a));
	if( !mf.Calendar.alt ){
		mf.Calendar.alt = document.createElement("div");
		mf.Calendar.alt.style.position = "absolute";
		mf.Calendar.alt.style.visibility = "hidden";
		mf.Calendar.alt.className = "mf_date_alt";
		var ary_emt = document.getElementsByTagName("body");
		ary_emt[0].appendChild(mf.Calendar.alt);
	}

	//自分の上
	var x = mf.getAbsoluteX(obj_a) + (obj_a.offsetWidth/2);
	var y = mf.getAbsoluteY(obj_a) - (obj_a.offsetHeight * 1.4);
	
	mf.Calendar.alt.innerHTML = str_chg;
	mf.Calendar.alt.style.left = x + "px";
	mf.Calendar.alt.style.top = y + "px";
	mf.Calendar.alt.style.visibility = "visible";

	//mouseoutイベントの登録
	var date_mouseout = function(e) {
//		alert("mouseout:"+e.currentTarget.childNodes.length);
		mf.Calendar.alt.style.visibility = "hidden";
		mf.Handler.remove(e.currentTarget, "mouseout", date_mouseout );

	}
	mf.Handler.add(obj_a, "mouseout", date_mouseout );
}

/*****************************************************************************
* コンストラクタ
* 書式：  mf.Calendar2( string tag_id[, object obj_prm] );
*
* @param    tag_id				カレンダーを作るタグのID名
* @param    obj_prm.date		日付オブジェクト　省略したら今月
* @param    obj_prm.past		表示したい過去の月数　省略したら表示なし
* @param    obj_prm.future		表示したい未来の月数　省略したら表示なし
* @param    obj_prm.title		タイトル　省略したら"Calendar"
* @param    obj_prm.user		ユーザID　省略したらリンクなし
*****************************************************************************/
mf.Calendar2 = function(tag_id, obj_prm) {
	//プロパティ
	this.id = tag_id;		//タグ名
	//オプション 日付オブジェクト　省略したら今月
	if( !obj_prm || !obj_prm.date ){
		this.date = new Date();
	} else {
		this.date = obj_prm.date;	//カレンダーを作る日付のオブジェクト
	}
	//オプション 表示したい過去の月数
	if( !obj_prm || !obj_prm.past ){
		this.past = 0;
	} else {
		this.past = parseInt(obj_prm.past,10);
	}
	//オプション 表示したい未来の月数
	if( !obj_prm || !obj_prm.future ){
		this.future = 0;
	} else {
		this.future = parseInt(obj_prm.future,10);
	}
	//オプション タイトル
	if( !obj_prm || !obj_prm.title ){
		this.str_title = "Calendar";
	} else {
		this.str_title = obj_prm.title.toString();
	}
	//オプション ユーザID
	if( !obj_prm || !obj_prm.user ){
		this.user_id = 0;
	} else {
		this.user_id = parseInt(obj_prm.user, 10);
	}

	//タイトルと操作メニュー
	this.menu = document.createElement("div");
	this.menu.className = "mf_c_menu";
	this.menu.id = "mf_c_menu";
	document.getElementById(this.id).appendChild(this.menu);

	var obj_date = new Date(this.date.getFullYear(),this.date.getMonth()-this.past,1);
	this.makeMenu(obj_date.getFullYear(), obj_date.getMonth());

	//今日の日付表示
	this.now = document.createElement("div");
	this.now.className = "mf_c_menu_today";
	this.now.id = "mf_c_menu_today";
	this.now.innerHTML = "<a href=\"javascript:mf.Calendar.goToday('"+this.id+"');\" class=\"mf_c_menu\">"
		+this.date.getFullYear()+"年"+(this.date.getMonth()+1)+"月"+this.date.getDate()+"日"
		+"</a>";
	document.getElementById(this.id).appendChild(this.now);
	
	//カレンダー作成
	this.setCalendar();

//	alert(list_nodes(document.getElementById(this.id)));
}

mf.Calendar2.prototype.change = function(offset_year, offset_month) {
	var min_year = 0;
	var min_month = 0;
	var max_year = 0;
	var max_month = 0;

	var int_no = 1; //カレンダーの連番
	for( var i=-this.past; i<=this.future; i++ ){
		var calendar = this.getCalendar(int_no);
		if( calendar ){
			var ary_obj = calendar.getElementsByTagName("caption");
			if( ary_obj.length==0 ) continue;
			var caption = ary_obj[0];
	
			var ary_cpt = caption.innerHTML.split("年");
			var int_year = parseInt(ary_cpt[0].substr(ary_cpt[0].length-4,4), 10);
			ary_cpt = ary_cpt[1].split("月");
			var int_month = parseInt(ary_cpt[0], 10)-1;

			var obj_date = new Date(int_year+offset_year,int_month+offset_month,1);

			this.makeCalendar(calendar,obj_date.getFullYear(),obj_date.getMonth(),0);

			if( int_no==1 ){
				min_year = obj_date.getFullYear();
				min_month = obj_date.getMonth();
			}
			max_year = obj_date.getFullYear();
			max_month = obj_date.getMonth();
		}
		int_no++;
	}

	if( min_year!=0 ){
		this.makeMenu(min_year, min_month);

		//日付リンクデータの読み込み
		this.load_links(min_year,min_month,max_year,max_month);
	}
}

mf.Calendar2.prototype.getCalendar = function(int_no) {
	var obj_prnt = document.getElementById(this.id);
	if( !obj_prnt ) return null;

	for(var i=0; i<obj_prnt.childNodes.length; i++){
		var str_id = "mf_calendar_"+int_no;
		if( obj_prnt.childNodes[i].id==("mf_calendar_"+int_no) ){
			return obj_prnt.childNodes[i];
		}
	}
	return null;
}

mf.Calendar2.prototype.makeMenu = function(int_year,int_month) {
	//操作メニュー
	if( this.menu.id!="mf_c_menu" ) return;

	//タイトル
	var str_title = this.str_title;
	if( str_title.charAt(0)!=" " ){
		str_title = " "+str_title+" ";
	}

	var str_id = this.menu.parentNode.id;
	if( int_year==2000 ){
		var str_ih = "&nbsp;&nbsp";
	} else {
		str_ih = "<a href=\"javascript:mf.Calendar.lastYear('"+str_id+"');\" class=\"mf_c_menu\">&lt;&lt;</a> ";
	}
	if( int_year==2000 && int_month<=0 ){
		str_ih += "&nbsp;&nbsp;&nbsp;";
	} else {
		str_ih += "<a href=\"javascript:mf.Calendar.lastMonth('"+str_id+"');\" class=\"mf_c_menu\">&lt;</a>";
	}
	this.menu.innerHTML = str_ih
		+str_title
		+"<a href=\"javascript:mf.Calendar.nextMonth('"+str_id+"');\" class=\"mf_c_menu\">&gt;</a> "
		+"<a href=\"javascript:mf.Calendar.nextYear('"+str_id+"');\" class=\"mf_c_menu\">&gt;&gt;</a>";
}

//カレンダー作成又は変更
mf.Calendar2.prototype.setCalendar = function(int_year, int_month, int_date) {
	var obj_prnt = document.getElementById(this.id);
	if( !obj_prnt ) return;

	if( !int_year ){
		int_year = this.date.getFullYear();
	} else {
		int_year = parseInt(int_year, 10);
	}
	if( !int_month ){
		int_month = this.date.getMonth();
	} else {
		int_month = parseInt(int_month, 10);
	}
	if( !int_date ){
		int_date = this.date.getDate();
	} else {
		int_date = parseInt(int_date, 10);
	}

	//カレンダー作成又は変更
	var int_no = 1; //カレンダーの連番
	for( var i=-this.past; i<=this.future; i++ ){
		var obj_date = new Date(int_year,int_month+i,1);

		var calendar = this.getCalendar(int_no);
		if( !calendar ){
			calendar = document.createElement("table");
			calendar.className = "mf_calendar";
			calendar.id = "mf_calendar_" + int_no;

			this.makeCalendar(calendar,obj_date.getFullYear(),obj_date.getMonth(),(i==0?int_date:0));
			obj_prnt.appendChild(calendar);
		} else {
			this.makeCalendar(calendar,obj_date.getFullYear(),obj_date.getMonth(),(i==0?int_date:0));
		}
		int_no++;
	}
	
	//日付リンクデータの読み込み
	obj_date = new Date(int_year,int_month-this.past,1);
	var min_year = obj_date.getFullYear();
	var min_month = obj_date.getMonth();
	obj_date = new Date(int_year,int_month+this.future,1);
	var max_year = obj_date.getFullYear();
	var max_month = obj_date.getMonth();
	
	this.load_links(min_year,min_month,max_year,max_month);
}

mf.Calendar2.prototype.load_links = function(min_year,min_month,max_year,max_month) {

	if( this.user_id<=0 ){
		return;
	}
	str_month = "0"+(min_month+1).toString();
	str_month = str_month.substr(str_month.length-2,2);
	var str_url = "http://www.mathomfactory.com/map/mfc_"+this.user_id+"_"+min_year+str_month+".xml";
//	var str_url = "mfc_"+this.user_id+"_"+min_year+str_month+".xml";
	//プログラムの場合は
//	var str_url = "http://www.mathomfactory.com/map/mfc_load_links.php?id="+this.user_id+"&y="+min_year+"&m="+min_month+"&t="+this.id;
	
	//日付リンク情報のXMLデータをリクエスト
	mf.Http.loadXML(str_url, mf.Calendar2._getResponse);
}

mf.Calendar2._getResponse = function(responseXML) {

	var xml_datas = responseXML.getElementsByTagName("link_datas");
	var tag_id = xml_datas[0].getAttribute("tag_id"); //カレンダーを作ったタグのid
	var element = xml_datas[0].getElementsByTagName("link");

	var obj_tds = document.getElementById(tag_id).getElementsByTagName("td");

	for(var i=0; i<obj_tds.length; i++){
		if( obj_tds[i].id.substr(0,String("mf_c_").length)!="mf_c_" ){
			//日付tdタグではない
			continue;
		}
		var id = obj_tds[i].id.substr(String("mf_c_").length);
		for(var j=0; j<element.length; j++){
			if( id==element[j].getAttribute("id") ){
				//XMLにこの日付のリンク情報があった
				var url = element[j].getAttribute("url");
				var str_data = mf.Http._getTextNodeData(element[j]);
				//クラス名作成
				var str_class = "mf_date";
				var ary_class = obj_tds[i].className.split(" ");
				if( mf.searchAry(ary_class,"mf_today")!==false ){
					//今日ならクラス名の変更
					str_class = "mf_today";
				}
				var int_date = parseInt(id.substr(6,2),10);
				//カレンダーの日付にURLをセット
				obj_tds[i].innerHTML = "<a href=\""+url+"\" class=\""+str_class+"\" onmouseover=\"mf.Calendar.date_mouseover(this,'"+str_data+"')\">"+int_date+"</a>";
			}
		}
	}
}

mf.Calendar2.prototype.makeCalendar = function(calendar,int_year,int_month,int_date) {

//	//年月選択メニュー
//	var str_ih = mf.Calendar.getSelectYear(this.date.getFullYear())+"年";
//	str_ih += mf.Calendar.getSelectMonth(this.date.getMonth())+"月";
//	str_ih += "<button type=\"button\" name=\"mf_c_btn\ id=\"mf_c_btn\" class=\"mf_c_btn\">GO</button>";

	var ary_cpt = calendar.getElementsByTagName("caption");
	if( ary_cpt.length<1 ){
		var caption = document.createElement("caption");
		caption.className = "mf_month";
	} else {
		caption = ary_cpt[0];
	}

//	caption.onmouseover = mf.Calendar.month_mouseover;
//	caption.innerHTML = str_ih;
	caption.innerHTML = int_year+"年"+(int_month+1)+"月";
//	caption.innerHTML = obj_date.getFullYear()+"年"+(obj_date.getMonth()+1)+"月";
//	caption.appendChild(document.createTextNode(obj_date.getFullYear()+"年"+(obj_date.getMonth()+1)+"月"));
	if( ary_cpt.length<1 ){
		calendar.appendChild(caption);
	}

	var week = 0;
	var date = 0;

	var ary_cpt = calendar.getElementsByTagName("thead");
	if( ary_cpt.length<1 ){
		var thead = document.createElement("thead");

		week = document.createElement("tr");
		for( var i=0; i<7; i++ ){
			date = document.createElement("th");
			date.className = "mf_week_title";
			switch(i){
			case 0:
				date.innerHTML = "日";
				break;
			case 1:
				date.innerHTML = "月";
				break;
			case 2:
				date.innerHTML = "火";
				break;
			case 3:
				date.innerHTML = "水";
				break;
			case 4:
				date.innerHTML = "木";
				break;
			case 5:
				date.innerHTML = "金";
				break;
			case 6:
				date.innerHTML = "土";
				break;
			}
			week.appendChild(date);
		}
		thead.appendChild(week);
		calendar.appendChild(thead);
	}

	var tbody = document.createElement("tbody");

	//当月1日
	var obj_date = new Date(int_year,int_month,1);
	//日曜日の日付　1日以前なら0以下
	var start = 1 - obj_date.getDay();
	//来月1日
	var obj_last = new Date(obj_date.getFullYear(),obj_date.getMonth()+1,1);
	//当月末日
	obj_last = new Date(obj_last.getTime()-1);
	var end = obj_last.getDate();
	//振り替え休日チェックフラグクリア
	mf.Calendar2.lieu_flg = false;
	//年月の文字列
	var str_ym = "0"+(int_month+1).toString();
	str_ym = str_ym.substr(str_ym.length-2,2);
	str_ym = int_year.toString() + str_ym;
	//今日
//	var obj_today = new Date();
	var obj_today = this.date;

	while( start<=end ){
		week = document.createElement("tr");
		week.className = "mf_week";
		for( var i=0; i<7; i++ ){
			date = document.createElement("td");
			date.className = "mf_date";
			if( start>0 && start<=end ){
				date.appendChild(document.createTextNode(start));
				var str_id = start.toString();
				if( str_id.length<2 ) str_id = "0"+str_id;
				date.id = "mf_c_" + str_ym + str_id; //"mf_c_"+年月日の文字列
				if( mf.Calendar2.isHoliday(obj_date.getFullYear(),obj_date.getMonth(),start) ){
					date.className += " mf_holiday";
				} else {
					switch(i){
					case 0:
						date.className += " mf_sun";
						break;
					case 6:
						date.className += " mf_sat";
						break;
					}
				}
				if( obj_today.getFullYear()==obj_date.getFullYear()
				   && obj_today.getMonth()==obj_date.getMonth()
				   && obj_today.getDate()==start ){
					date.className += " mf_today";
				}
			} else {
				date.appendChild(document.createTextNode(""));
			}
			week.appendChild(date);
			start++;
		}
		tbody.appendChild(week);
	}

	var ary_cpt = calendar.getElementsByTagName("tbody");
	if( ary_cpt.length<1 ){
		calendar.appendChild(tbody);
	} else {
		calendar.replaceChild(tbody,ary_cpt[0])
	}
//	alert(list_nodes(document.getElementById(this.id)));
}

// mf.Calendar.month_form = null;
//	
// mf.Calendar.month_mouseover = function()
// {
// //	alert(list_nodes(obj_c));
//	if( !mf.Calendar.month_form ){
//		mf.Calendar.month_form = document.createElement("div");
//		mf.Calendar.month_form.style.position = "absolute";
//		mf.Calendar.month_form.style.visibility = "hidden";
//		mf.Calendar.month_form.className = "mf_date_alt";
//		var ary_emt = document.getElementsByTagName("body");
//		ary_emt[0].appendChild(mf.Calendar.month_form);
//	}
// 
//	//自分の位置
//	var x = mf.getAbsoluteX(this);
//	var y = mf.getAbsoluteY(this);
//	//カレンダーの現在の年月
//	var ary_ym = this.innerHTML.split("年");
//	var int_year = parseInt(ary_ym[0],10);
//	var int_month = parseInt(ary_ym[1].slice(0,-1),10);
//	
//	var obj_date = new Date();
//	var str_ih = mf.Calendar.getSelectYear(obj_date.getFullYear());
//	str_ih += mf.Calendar.getSelectMonth(obj_date.getMonth());
//	str_ih += "<button type=\"button\" name=\"mf_c_btn\ id=\"mf_c_btn\">GO</button>";
// 
//	mf.Calendar.month_form.innerHTML = str_ih;
//	mf.Calendar.month_form.style.left = x + "px";
//	mf.Calendar.month_form.style.top = y + "px";
//	mf.Calendar.month_form.style.visibility = "visible";
// 
//	//mouseoutイベントの登録
//	var month_mouseout = function(e) {
// //		alert("mouseout:"+e.currentTarget.childNodes.length);
// 
//		//マウスの位置
//		var m_x = e.clientX + mf.win.getHorizontalScroll();
//		var m_y = e.clientY + mf.win.getVerticalScroll();
//		//自分の領域
//		var left = mf.getAbsoluteX(e.currentTarget);
//		var top = mf.getAbsoluteY(e.currentTarget);
//		var right = left + e.currentTarget.offsetWidth-1;
//		var bottom = top + e.currentTarget.offsetHeight-1;
//		//自分の領域の外なら処理
//		//注）IEでマウス位置と領域の座標が2ずれる。対策として左と上に2加える
//		if( m_x<left+2 || right<m_x || m_y<top+2 || bottom<m_y ){
//			e.currentTarget.style.visibility = "hidden";
//			e.stopPropagation();
//			mf.Handler.remove(e.currentTarget, "mouseout", month_mouseout );
//		}
//	}
//	mf.Handler.add(mf.Calendar.month_form, "mouseout", month_mouseout );
// }
//	
// mf.Calendar.getSelectYear = function(now_year)
// {
//	//カレンダーの現在の年
//	var int_year = parseInt(now_year,10);
// 
//	var str_ih = "<select name=\"mf_c_year\" id=\"mf_c_year\" class=\"mf_c_select\">";
//	for(var i=2008; i<=int_year+2; i++){
//		if( i==int_year ){
//			var str_s = " selected=\"selected\"";
//		} else {
//			str_s = "";
//		}
//		str_ih += "<option value=\""+i+"\""+str_s+">"+i+"</option>";
//	}
//	str_ih += "</select>";
//	return str_ih;
// }
//	
// mf.Calendar.getSelectMonth = function(now_month)
// {
//	//カレンダーの現在の月
//	var int_month = parseInt(now_month,10)+1;
// 
//	var str_ih = "<select name=\"mf_c_month\" id=\"mf_c_month\" class=\"mf_c_select\">";
//	for(var i=1; i<=12; i++){
//		if( i==int_month ){
//			var str_s = " selected=\"selected\"";
//		} else {
//			str_s = "";
//		}
//		str_ih += "<option value=\""+i+"\""+str_s+">"+i+"</option>";
//	}
//	str_ih += "</select>";
//	return str_ih;
// }

mf.Calendar2.lieu_flg = false;
	
mf.Calendar2.isHoliday = function(int_year,int_month,int_date) {
	//注）int_monthはJavaScriptに合わせ0～11

	//自分自身が祝日か
	if( mf.Calendar2.isHolidaySub(int_year,int_month,int_date) ){
		//日曜か
		var obj_date = new Date(int_year,int_month,int_date);
		if( obj_date.getDay()==0 ){
			//振替休日が必要
			mf.Calendar2.lieu_flg = true;
		}
		
		return true;
	}
	
	//振替休日か
	if( mf.Calendar2.lieu_flg ){
		mf.Calendar2.lieu_flg = false;
		return true;
	}
	
	//前日と翌日が祝日か
	var obj_before = new Date(int_year,int_month,parseInt(int_date,10)-1);
	var obj_next = new Date(int_year,int_month,parseInt(int_date,10)+1);
	if( mf.Calendar2.isHolidaySub(obj_before.getFullYear(),obj_before.getMonth(),obj_before.getDate())
	   && mf.Calendar2.isHolidaySub(obj_next.getFullYear(),obj_next.getMonth(),obj_next.getDate()) ){
		return true;
	}
	return false;
}

mf.Calendar2.isHolidaySub = function(int_year,int_month,int_date) {
	//注）int_monthはJavaScriptに合わせ0～11

	//固定日の祝日か
	var ary_date = mf.Calendar2.ary_hldy_date[int_month];
	for( var i=0; i<ary_date.length; i++ ){
		if( int_date==ary_date[i] ){
			return true;
		}
	}

	var obj_date = new Date(int_year,int_month,int_date);
	if( obj_date.getDay()==1 ){
		//月曜日なら祝日かも
		var week_no = parseInt((int_date - obj_date.getDay() -1) / 7, 10) +1;
		ary_date = mf.Calendar2.ary_hldy_week[int_month];
		for( var i=0; i<ary_date.length; i++ ){
			if( week_no==ary_date[i] ){
				return true;
			}
		}
	}
	
	//春分か
	if(int_month==2){ //3月なら
		if( int_date==mf.Calendar2.getSpringEquinox(int_year) ){
			return true;
		}
	}
	
	//秋分か
	if(int_month==8){ //9月なら
		if( int_date==mf.Calendar2.getAutumnalEquinox(int_year) ){
			return true;
		}
	}
	return false;
}

mf.Calendar2.ary_hldy_date = [
								[1],	//1
								[11],	//2
								[],	//3
								[29],	//4
								[3,4,5],	//5
								[],	//6
								[],	//7
								[],	//8
								[],	//9
								[],	//10
								[3,23],	//11
								[23]	//12
							];

mf.Calendar2.ary_hldy_week = [
								[2],	//1
								[],	//2
								[],	//3
								[],	//4
								[],	//5
								[],	//6
								[3],	//7
								[],	//8
								[3],	//9
								[2],	//10
								[],	//11
								[]	//12
							];

mf.Calendar2.getSpringEquinox = function(int_year) {
	//2000年の太陽の春分点通過日
	var eq = 20.69115;
	//１年ごとの春分点通過日の移動量
	var int_num = (int_year - 2000) * 0.2421904;
	//閏年によるリセット量
	var int_reset = parseInt((int_year - 2000) / 4, 10);
	return parseInt(eq + int_num - int_reset, 10);
}

mf.Calendar2.getAutumnalEquinox = function(int_year) {
	//2000年の太陽の秋分点通過日
	var eq = 23.09;
	var int_num = (int_year - 2000) * 0.2421904;
	var int_reset = parseInt((int_year - 2000) / 4, 10);
	return parseInt(eq + int_num - int_reset, 10);
}

