/* createCalendar.js ver1.0 Copyright (c)2006 No1 travel Web Site Planning Div.(TOKYO) All Rights Reserved */

/*==============================================*/
//カレンダー自動作成.js
//2006/11/22	ver.0.1	作成開始
//2006/11/28	ver.0.5	末端＆メニュー機能OK
/*==============================================*/

/*---------------------------------*/
/* 設定 */
/*---------------------------------*/

//ap + CLEAR_DATE分料金消えます
//デフォルトでエクセルにて"3"になってます。
CLEAR_DATE = 0;

/*=====================================*/
/* Query class : クエリ作成 */
/*=====================================*/
var Query = Class.create();
Query.prototype = {
	initialize : function(){
		this.url = location.pathname;
	},
	getPageName : function(){
		var u = this.url.split('\/');
		var pageName = u[u.length -1].split('\.')[0];
		return pageName;
	}
}

/*=====================================*/
/* FareList class : 料金のリスト */
/*=====================================*/
var FareList = Class.create();
FareList.prototype = {
	initialize : function(){
		this.list = [];
	},
	add : function(fare){
		//ap削除
		fare.clearAp();
		this.list.push(fare);
	},
	createMinFares : function(){
		var minFare = [];
		for(var i = 0; i < this.list[0].fare.length; i++){
			//その一日の料金リスト
			var tmpFareList = [];
			for(var j = 0; j < this.list.length; j++){
				var f = Number(this.list[j].fare[i]);
				if(f > 0){
					tmpFareList[j] = f;
				}
			}
			minFare.push(tmpFareList.min());
		}
		return minFare;
	},
	getReg : function(){
		return this.list[0].reg;
	},
	getRoute : function(){
		return this.list[0].route;
	},
	getLastupdate : function(){
		return this.list[0].lastupdate;
	},
	getCourse : function(){
		return this.list[0].course;
	},
	getArea : function(){
		return this.list[0].area;
	},
	getPage : function(){
		return this.list[0].page;
	}
}

/*=====================================*/
/* AirFare class : 料金クラス */
/*=====================================*/
var AirFare = Class.create();
AirFare.prototype = {
	initialize : function(airFare){
		this.page = airFare.page;
		this.course = airFare.course;
		this.area = airFare.dep;
		this.id = airFare.id;
		this.ap = airFare.ap;
		this.min = airFare.min;
		this.max = airFare.max;
		var start = airFare.start.split('\/');
		this.startYear = start[0];
		this.startMonth = start[1];
		this.fare = airFare.fare;
		this.c = new Calendar(this.startYear, this.startMonth);
		this.reg = this.changeReg(airFare.reg);
		this.route = airFare.city;
		this.lastupdate = airFare.lastupdate;
	},
	clearAp : function(){
		/* カレンダーのスタート日から、APの日が何日後か求める。*/
		var fareStartDay = [];
		fareStartDay['y'] = this.startYear;
		fareStartDay['m'] = this.startMonth;
		fareStartDay['d'] = 1;
		
		//今日とカレンダーのスタート日の差を取得
		var diff = this.c.getDifference(fareStartDay, TODAY);
		
		//差を基準にAPを調整
		var ap = Number(this.ap) + diff + this.clearDate();
		
		//ap分料金clear(apの日にち分、料金を-1に変換)
		for(var i =0; i < ap; i++){
			this.fare[i] = -1;
		}
	},
	clearDate : function(){
		return CLEAR_DATE + 1;
	},
	changeReg: function(reg){
		if(reg == '0 - 0 One&nbsp;way'){
			res = "One way";
		}else{
			res = reg;
		}
		return res;
	}
}

/*=====================================*/
/* Calendar class : 日付全般を扱う */
/*=====================================*/
var Calendar = Class.create();
Calendar.prototype = {
	initialize : function(year, month){
		this.year = Number(year);
		this.month = Number(month);
		this.monthDays = this.getDays(this.year, this.month);
		this.firstDay = this.zeller(this.year, this.month, 1);
	},
	getDays : function(year, month){
		var month = Number(month) - 1;
		var monthDays = new Array("31", "28", "31", "30", "31", "30", "31", "31", "30", "31", "30", "31");
		if(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)){
			monthDays[1] = 29;
		}
		return monthDays[month];
	},
	zeller : function(year, month, day){
		var y = Number(year);
		var m = Number(month) + 1;
		var d = Number(day);
		//1月と2月の調整
		if(m == 1 || m == 2){
			y -= 1
			m += 12
		}
		return (y + Math.floor((y / 4)) - Math.floor((y / 100)) + Math.floor((y / 400)) + (Math.floor((13 * m + 8) / 5)) + d) % 7;
	},
	getWeeks : function(days, firstDay){
		var days = Number(days);
		var firstDay = Number(firstDay);
		var a = (days + firstDay) % 7;
		var b = Math.ceil(((days + firstDay) / 7));
		if(a != 0){
			return b;
		}else{
			return b;
		}
	},
	//基準日のafter日後を取得
	getAfterDate : function(after, y , m, d){
		var s = after * 1000 * 60 * 60 * 24;
		
		//基準日セット
		var targetDate = new Date();
		targetDate.setFullYear(y);
		targetDate.setMonth(m);
		targetDate.setDate(d);
		
		//日付を求める
		var DateInMS = targetDate.getTime();
		DateInMS += s;
		targetDate.setTime(DateInMS);
		
		var theYear = targetDate.getFullYear();
		var theMonth = targetDate.getMonth() + 1;
		var theDate = targetDate.getDate();
		var res = [];
		res['y'] = theYear;
		res['m'] = theMonth;
		res['d'] = theDate;
		return res;
	},
	//2つの日付の差を取得
	getDifference : function(base, target){
		var baseDate = new Date();
		var targetDate = new Date();
		
		baseDate.setFullYear(base['y']);
		baseDate.setMonth(base['m']);
		baseDate.setDate(base['d']);
		
		targetDate.setFullYear(target['y']);
		targetDate.setMonth(target['m']);
		targetDate.setDate(target['d']);
		
		var res =  targetDate.getTime() - baseDate.getTime();
		res = Math.floor(res / (1000 * 60 * 60 * 24));
		return res;
	},
	getDifference2 : function(base, target){
		//年越しの場合、要コード追加
		if(base['y'] == target['y']){
			var res = 0;
			var numOfMonth = target['m'] - base['m'] + 1;
			for(var i = 0; i < numOfMonth; i++){
				res += Number(this.getDays(base['y'], (Number(base['m']) + i)));
			}
			
			res -= Number(this.getDays(target['y'], target['m']) - target['d'] + 1);
		}
		return res;
	}
}

/*=====================================*/
/* CreateHtml class : HTML作成クラス */
/*=====================================*/
var CreateHtml = Class.create();
CreateHtml.prototype = {
	initialize : function(fare){
		this.fare = fare;
		this.c = new Calendar(this.fare.list[0].startYear, this.fare.list[0].startMonth);
		this.startMonth = Number(this.fare.list[0].startMonth) - 1;
		this.startYear = Number(this.fare.list[0].startYear);
		this.numberOfMonth = this.getNumberOfMonth();
		this.monthName = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
		this.monthFullName = ['JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER'];
		this.link = '';
	},
	getNumberOfMonth : function(){
		var fares = this.fare.list[0].fare.length;
		var n = Math.round(fares / 30);
		return n;
	},
	create : function(){
		//最安値リスト作成
		var miniFares = this.fare.createMinFares();
		
		var html = [];
		//データが存在しない場合
		if(this.fare.list.length == 0){
			html = 'no data';
		}else{
		//データが存在
			var fareCount = 0;
			for(var i = 0; i < this.numberOfMonth; i++){
				var monthHtml = [];
				
				//月と年,変数を設定
				var tmpYear = this.startYear;
				var tmpMonth = this.startMonth + i;
				var countDay = 1;
				var availableFares = 0;
				
				//年をまたぐ場合の処理
				if(tmpMonth > 11){
					tmpMonth -= 12;
					tmpYear += 1;
				}
				//その月の日数
				var days = this.c.getDays(tmpYear, (tmpMonth + 1));
				//その月の1日の曜日
				var firstDay = this.c.zeller(tmpYear, tmpMonth, 1);
				//その月の週数
				var weeks = this.c.getWeeks(days, firstDay);
				
				//ページ内リンク作成
				monthHtml.push('<a name="' + this.monthName[tmpMonth] + '"></a>');
								
				//カレンダーのheader作成
				monthHtml.push(this.createCalHead(tmpYear, tmpMonth));
				
				//週数分ループ
				for(var j = 0; j < weeks; j++){
					monthHtml.push('<tr align="center">');
					//日数分ループ
					for(var k = 0; k < 7; k++){
						var fare = miniFares[fareCount];
						if(typeof(fare) == 'number' && countDay <= days){
							fare = (fare * 10) * 100;
							//3桁ごとにコンマ入れる
							fare = fare.toString().replace(/([0-9]+?)(?=(?:[0-9]{3})+$)/g,'$1,');
							availableFares++;
						}else{
							fare = '&nbsp;';
						}
						
						//最初の週
						if(j == 0){
							if(k < firstDay){
								monthHtml.push(this.createVoidCell(k));
							}else{
								monthHtml.push(this.createCell(countDay, fare, k));
								fareCount++;
								countDay++;
							}
						//最後の週
						}else if(j == (weeks - 1)){
							if(countDay > days){
								monthHtml.push(this.createVoidCell(k));
							}else{
								monthHtml.push(this.createCell(countDay, fare, k));
								fareCount++;
								countDay++;
							}
						//その他
						}else{
							monthHtml.push(this.createCell(countDay, fare, k));
							fareCount++;
							countDay++;
						}
					}
					monthHtml.push('</tr>');
				}
				monthHtml.push('</table>');
				
				//カレンダー間のスペースを入れる
				monthHtml.push(this.createSpace(i));
				
				//料金が1日でも存在すればhtmlに追加
				if(Number(availableFares) != 0){
					html.push(monthHtml.join("\n"));
					//monthlink作成
					this.link += '&gt;&gt; <a href="#' + this.monthName[tmpMonth] + '">' + this.monthName[tmpMonth].toUpperCase() + '</a>&nbsp;';
				}
			}
		}
		return html.join("\n");
	},
	/*---------- calendar部品 ----------*/
	createCalHead : function(year, month){
		var header = [];
		
		header.push('<table width="100%" border="0" cellspacing="1" cellpadding="1" bgcolor="#C0C0C0" id="' + this.monthName[10] +' ">');
		header.push('<tr align="center" valign="middle" bgcolor="#999999">');
		header.push('<td colspan="7" class="month">' + this.monthFullName[month] + ', ' + year + '</td>');
		header.push('</tr>');
		header.push('<tr align="center">');
		header.push('<td width="14%" bgcolor="#FFCCCC">Sun</td>');
		header.push('<td width="14%" bgcolor="#EAEAEA">Mon</td>');
		header.push('<td width="14%" bgcolor="#EAEAEA">Tue</td>');
		header.push('<td width="14%" bgcolor="#EAEAEA">Wed</td>');
		header.push('<td width="14%" bgcolor="#EAEAEA">Thu</td>');
		header.push('<td width="14%" bgcolor="#EAEAEA">Fri</td>');
		header.push('<td width="14%" bgcolor="#B4EDF8">Sat</td>');
		header.push('</tr>');
		
		return header.join("\n");
	},
	createSpace : function(i){
		//最後の月以外は実行
		if(i != (this.numberOfMonth -1)){
			var space = [];
			space.push('<table width="100%"  border="0" cellspacing="0" cellpadding="0">');
			space.push('<tr><td align="right"><a href="#">▲TOP</a></td></tr>');
			space.push('</table>');
			return space.join("\n");
		}
	},
	//空の日付作成
	createVoidCell : function(k){
		//日曜ならbgをピンクに
		if(k == 0){
			return '<td bgcolor="#FFECEC">&nbsp;<br>&nbsp;</td>';
		//土曜ならbgを水色に
		}else if(k == 6){
			return '<td bgcolor="#E3F9FD">&nbsp;<br>&nbsp;</td>';
		//平日ならbgを白に
		}else{
			return '<td bgcolor="#FFFFFF">&nbsp;<br>&nbsp;</td>';
		}
		
	},
	//料金ありの日付作成
	createCell : function(day, fare, k){
		//日曜ならbgをピンクに
		if(k == 0){
			return '<td bgcolor="#FFECEC">' + day + '<br><span class="gr">' + fare + '</span></td>'
		//土曜ならbgを水色に
		}else if(k == 6){
			return '<td bgcolor="#E3F9FD">' + day + '<br><span class="gr">' + fare + '</span></td>'
		//平日ならbgを白に
		}else{
			return '<td bgcolor="#FFFFFF">' + day + '<br><span class="gr">' + fare + '</span></td>'
		}
	},
	cretaeMonthLink : function(){
		var link = this.link;
		//for(var i = 0; i < (this.numberOfMonth -1); i++){
		//	var tmpMonth = (this.startMonth + 1) + i;
		//	if(tmpMonth > 11){
		//		tmpMonth -= 12;
		//	}
		//	link += '&gt;&gt; <a href="#' + this.monthName[tmpMonth] + '">' + this.monthName[tmpMonth].toUpperCase() + '</a>&nbsp;';
		//}
		return link;
	}
}

/*=====================================*/
/* Display class : 表示クラス */
/*=====================================*/
var Display = Class.create();
Display.prototype = {
	initialize : function(id, html){
		this.id = id;
		this.html = html;
	},
	show : function(){
		$(this.id).innerHTML = this.html;
	}
}

/*=====================================*/
/* JsonData class : jsonデータを扱う */
/*=====================================*/
var JsonData = Class.create();
JsonData.prototype = {
	initialize : function(pageName){
		var dateMs = new Date().getTime();
		this.path = '../json/' + pageName + '.txt?' + dateMs;
	},
	getAndShow : function(){
		new Ajax.Request(
		this.path,
			{
				method : 'get',
				asynchronous : true,
				onSuccess : this.show,
				onFailure : this.noReplay
			}
		)
	},
	show : function(req){
		var fare = new FareList();
		var rowData = eval(req.responseText);
		for(var i = 0; i < rowData.length; i++){
			 fare.add(new AirFare(rowData[i]));
		}
		var html = new CreateHtml(fare);
		var res = new Display('calender', html.create());
		res.show();
		
		var reg = new Display('reg', fare.getReg());
		reg.show();
		
		var lastupdate = new Display('lastupdate', fare.getLastupdate());
		lastupdate.show();
				
		var route = new Display('route', fare.getRoute());
		route.show();
		
		var area = new Display('area', fare.getArea());
		area.show();
		
		//var monthLink = new Display('monthlink', html.cretaeMonthLink());
		//monthLink.show();
	},
	noReplay : function(req){
		var html = 'no data';
		var res = new Display('calendar', html);
		res.show();
	},
	getBottom : function(){
		new Ajax.Request(
		this.path,
			{
				method : 'get',
				asynchronous : true,
				onSuccess : this.createBottom,
				onFailure : this.noFare
			}
		)
	},
	createBottom : function(req){
		var bottom = 0;
		var fare = new FareList();
		var rowData = eval(req.responseText);
		for(var i = 0; i < rowData.length; i++){
			 fare.add(new AirFare(rowData[i]));
		}
		var name = fare.list[0].page;
		var fares = fare.createMinFares();
		bottom = fares.min();
		bottom = (bottom * 10)*100;
		//3桁ごとにコンマ入れる
		bottom = bottom.toString().replace(/([0-9]+?)(?=(?:[0-9]{3})+$)/g,'$1,');
		bottom = '<font color="red"><b>' + bottom + '-</b></font>';
		var res = new Display(name, bottom);
		res.show();
	},
	noFare : function(){
		var res = new Display(name, '');
		res.show();
	}
}

/*=====================================*/
/* Main class : カレンダー実行クラス */
/*=====================================*/
var Main = Class.create();
Main.prototype = {
	initialize : function(){
		q = new Query()
		this.pageName = q.getPageName();
	},
	execute : function(){
		var json = new JsonData(this.pageName);
		json.getAndShow();
	}
}

/*=====================================*/
/* Menu class : メニュー実行クラス */
/*=====================================*/
var Menu = Class.create();
Menu.prototype = {
	initialize : function(){
	},
	getBottom : function(pageName){
		var json = new JsonData(pageName);
		json.getBottom();
	}
}

