/* Auto-Bus Widget City File For Rouyn-Noranda, Quebec
 * Version 1.0.0
 * March 12th 2007
 * 
 * Copyright 2007 Frederic Weigand Warr
 *
 * This file is an addition to the Auto-Bus widget for the Yahoo! Widget Engine.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */


//-----------------------------------------------------------------------

/* This file contains code specific to Rouyn-Noranda's public transit system.
 * To make a city file for another transit system, use this as a template
 * and follow the instructions given in the comments above each function.
 * There are 7 functions that are necessary to implement to create a city
 * file. These are: getData, getTimes, getLineStr, getStpStr, getDirStr,
 * addStop and editStop. The first 5 (the getters) are methods of the
 * BusStop object and can therefore access the particular bus stop's info
 * through the keyword this. The last 2, are global functions to allow
 * the user to add STOPS and edit the STOPS list. Since these are global
 * functions, access to the bus STOPS is done through the "STOPS" array.
 * 
 * If you do create a functional city file for another transit system,
 * please send it to fwwarr@hotmail.com so that it can be posted on the
 * Auto-Bus widget's web page and be accessible for others to use.
 */

//------------------------------------------------------------------------
/* BusStop object methods
 */


/* method getData(doGetInfo)
 * 
 * Retrieves a bus stop's data from the web.
 * 
 * This is a method of the BusStop object
 * so the corresponding BusStop can be accessed
 * using "this" in the method body.
 * 
 * param doGetInfo
 * 
 *          If true, this method will call all of
 *          getTimes, getLineStr, getStpStr and getDirStr
 *          once the data has been received and appropriately
 *          refresh the display for all this information.
 *          
 *          If false, this method will only call getTimes
 *          once the data has been received and only the
 *          display of the times will be refreshed.
 * 
 * Note: Typically to adapt this method to a particular transit system
 * only the url location would have to be modified. Although this
 * may not be the case for every transit system.
 */
BusStop.prototype.getData = function (doGetInfo) {
	
	var url = new URL();
	// Do not modify above this line
	//------------------------------
	// Start of city specific code
	url.object = this
	if(doGetInfo){useData(url);}
	else{useTimeData(url);}
	return;
	
	// End of city specific code
	//-----------------------------
	//Do not modify below this line
	url.object = this;
	appendLineToFile(LOGPATH, "Fetching data for " + this.args[0]);
	if (doGetInfo) {
		url.fetchAsync(useData);
	} else {
		url.fetchAsync(useTimeData);
	}
}


/* method getTimes()
 * 
 * Extracts the next few passage times from the data fetched by the getData method.
 * That data is accessible to this method through "this.data".
 * 
 * This method is expected to return an array of Date objects.
 * 
 * This method is called after each bus passage so that the first element
 * of the array is always the very next passage time.
 * 
 * If there is no way of getting the next passage times (eg. there are no more passages today),
 * this method should return an empty array and appropriately modify this.nextUpdateTime
 * with a Date object representing the next time the widget should try to fetch the times.
 * 
 * The entirety of this method's code is city specific
 */
BusStop.prototype.getTimes = function () {
	var i,
		j,
		nextTimes,
		now,
		times;
	
	now = new Date();
	times = [];
	nextTimes = [];
	j = 0;
	if (this.args[0] == "10") {
		switch (parseInt(this.args[1])) {
		case 1: case 2: case 3: case 4: case 5: case 6:
			for(i in SCHEDULE10[0]){
				times[i] = convertToDate(SCHEDULE10[0][i]);
			}
			break;
		case 7: case 8: case 9: case 10: case 11: case 12:
			for(i in SCHEDULE10[1]){
				times[i] = convertToDate(SCHEDULE10[1][i]);
			}
			break;
		case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21:
			for(i in SCHEDULE10[2]){
				times[i] = convertToDate(SCHEDULE10[2][i]);
			}
			break;
		case 22: case 23: case 24: case 25: case 26: case 27: case 28:
			for(i in SCHEDULE10[3]){
				times[i] = convertToDate(SCHEDULE10[3][i]);
			}
			break;
		case 29: case 30: case 31: case 32: case 33: case 34: case 35:
			for(i in SCHEDULE10[4]){
				times[i] = convertToDate(SCHEDULE10[4][i]);
			}
			break;
		case 36: case 37:
			for(i in SCHEDULE10[5]){
				times[i] = convertToDate(SCHEDULE10[5][i]);
			}
			break;
		}
		for (i in times) {
			if (times[i]>now) {
				if (now.getDay()>0 && now.getDay()<4 && i<16) {
					nextTimes[j] = times[i];
				} else if (now.getDay()>3 && now.getDay()<6) {
					nextTimes[j] = times[i];
				}
				j++;
			}
		}
	}else if (this.args[0] == "20") {
		switch (parseInt(this.args[1])) {
		case 50: case 51: case 52: case 53: case 54: case 55:
			for(i in SCHEDULE20[0]){
				times[i] = convertToDate(SCHEDULE20[0][i]);
			}
			break;
		case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63:
			for(i in SCHEDULE20[1]){
				times[i] = convertToDate(SCHEDULE20[1][i]);
			}
			break;
		case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72:
			for(i in SCHEDULE20[2]){
				times[i] = convertToDate(SCHEDULE20[2][i]);
			}
			break;
		case 75: case 76: case 77: case 78: case 79:
			for(i in SCHEDULE20[3]){
				times[i] = convertToDate(SCHEDULE20[3][i]);
			}
			break;
		case 80: case 81: case 82: case 83: case 84:
			for(i in SCHEDULE20[4]){
				times[i] = convertToDate(SCHEDULE20[4][i]);
			}
			break;
		}
		for (i in times) {
			if (times[i]>now) {
				if (now.getDay()>0 && now.getDay()<4 && i<8) {
					nextTimes[j] = times[i];
				} else if (now.getDay()>3 && now.getDay()<6) {
					nextTimes[j] = times[i];
				}
				j++;
			}
		}
	}
	
	return nextTimes;
}

/* method getLineStr()
 * 
 * This method returns the string to display as the bus' line.
 * Typically this information is already stored in the bus stop's
 * args array at index 0, but if different information is required
 * from the web, the data accessed by getData is still accessible
 * through this.data.
 */
BusStop.prototype.getLineStr = function () {
	return "";
}

/* method getStpStr()
 * 
 * This method returns the string to display as the bus stop info.
 * 
 * Depending on the ciy, this string may be specified by the user 
 * and stored in the bus stop's args array at index 1, but typically
 * the info stored in args[1] is not an easily recognizable string
 * (i.e. it's just a stop number) and the string to display must be
 * extracted from the web data.
 * 
 * Alternatively, the user can be asked to specify this
 * string (as well as a bus stop number if necessary) upon
 * creation/modification of the bus stop (by methods addStop
 * and editStop) and stored in this.args[7]. In that case
 * this method would only have to return this.args[7].
 */
BusStop.prototype.getStpStr = function () {

	return "Circuit " + this.args[0];
}

/* method getDirStr()
 * 
 * This method returns the string to display as the direction
 * for which the times should be displayed.
 * 
 * Depending on the city, this string could be specified directly 
 * by the user and stored in args[2]. However, for some bus systems,
 * direction information is not needed to completely specify a bus stop
 * and the direction can be found on the web without the user specifying
 * it at all. (For example, in Montreal, a bus stop is fully qualified 
 * by a route number and a stop number and the direction corresponding
 * to that bus stop can be taken from the web.)
 * 
 * This method should not actually fetch data from the web but rather
 * use data fetched by getData and stored in this.data.
 */
BusStop.prototype.getDirStr = function () {
	
	return "Arrêt " + this.args[1];
}

//------------------------------------------------------------------------
/* Global functions
 */


/* function addStop()
 * 
 * Adds a bus stop to the array of STOPS to monitor.
 * Should create a form for the user to input the
 * necessary properties about the bus stop. A new
 * BusStop object created with the given properties
 * should then be added to the end of the STOPS array.
 * All other updating and displaying is taken care of
 * by non city specific code.
 * Typically the form should contain fields to specify
 * the route number, the stop name or number and sometimes
 * also the direction. These 3 properties should be stored
 * respectively in indexes 0, 1 and 2 of the  array.
 * This means that the BusStop object can be created simply
 * using the constructor BusStop(args) where args is an
 * array containing the three mentionned properties in
 * indexes 0 through 2.
 */
function addStop() {
	
	var formFields = new Array();
	var i = 0;
	formFields[i] = new FormField();
	formFields[i].title = "Circuit";
	formFields[i].type = "popup";
	formFields[i].option = ["10","20"];
	i++;
	formFields[i] = new FormField();
	formFields[i].title = "Arrêt";
	formFields[i].type = "text";
	
	var formResults = form( formFields, "Ajouter un arrêt", "OK" );
	
	if( formResults != null ){
		
		STOPS[STOPS.length] = new BusStop(formResults);
		
		// End of city specific code
		//------------------------------
		// Do not modify below this line
		STOPS[STOPS.length - 1].initDisplay();
		STOPS[STOPS.length - 1].getData(true);
		makeDisplay();
		saveStops();
	}
}

/* function editStop()
 * 
 * Provides the form for editing the basic properties of a bus stop.
 * Properties that define a particular bus stop should be specified
 * by the user in this form and saved in the BusStop object's args
 * array in indexes 0 through 2.
 * 
 * param busStop
 * 
 *           Indicates the indes of the STOPS array corresponding
 *           to the bus stop to be modified. The BusStop object to
 *           modify is therefore available through STOPS[busStop].
 * 
 * Typically, index 0 corresponds to the route number,
 * index 1 corresponds to the stop name or number, and
 * index 2 corresponds to the direction.
 * If additional information is needed to fully describe a bus stop,
 * indexes greater than 8 could be used.
 */
function editStop(busStop){
	
	var formFields = new Array();
	var i = 0;
	formFields[i] = new FormField();
	formFields[i].title = "Circuit";
	formFields[i].type = "popup";
	formFields[i].option = ["10","20"];
	formFields[i].value = STOPS[busStop].args[0];
	i++;
	formFields[i] = new FormField();
	formFields[i].title = "Arrêt";
	formFields[i].type = "text";
	formFields[i].value = STOPS[busStop].args[1];
	
	var formResults = form( formFields, "Edit bus stop", "OK" );
	
	if( formResults != null ){
		STOPS[busStop].args[0] = formResults[0];
		STOPS[busStop].args[1] = formResults[1];
		STOPS[busStop].args[2] = "";
		
		// End of city specific code
		//------------------------------
		// Do not modify below this line
		STOPS[busStop].getData();
		makeDisplay();
		saveStops();
	}
}



//--------------------------------------------------------------------------
/* Utility functions
 * 
 * Any other functions that may be used by the 7 previous functions but that
 * are not necessary to implement for every transit system should go here.
 */
 
// Converts the string from the schedule into a Date object
// Supports these formats:
// hh:mm (24h time)
function convertToDate(str){
	var now,
		hr,
		min;

	now = new Date();
	if(str.indexOf(":") > 0) {
		min = parseInt(str.substr(str.indexOf(":")+1, 2));
		hr = parseInt(str.substr(str.indexOf(":")-2, 2));
		now.setHours(hr);
		now.setMinutes(min);
		return now;
	}
	return "";
}

/*
 * To update the schedules, replace the times below with the new times.
 * Each row represents the the passage times at one stop interval as given
 * on the Rouyn-Noranda web site.
 * i.e for route 10, the first row is for stops 1 to 6, the second
 * for stops 7 to 12, etc.
 */

var SCHEDULE10 = [	["06:45","07:15","07:45","08:15","08:45","09:45","10:45","11:45","12:45","13:45","14:45","15:45","16:15","16:45","17:15","17:45","18:15","19:45","20:15","21:15"],
					["06:50","07:20","07:50","08:20","08:50","09:50","10:50","11:50","12:50","13:50","14:50","15:50","16:20","16:50","17:20","17:50","18:20","19:50","20:20","21:20"],
					["06:55","07:25","07:55","08:25","08:55","09:55","10:55","11:55","12:55","13:55","14:55","15:55","16:25","16:55","17:25","17:55","18:25","19:55","20:25","21:25"],
					["07:00","07:30","08:00","08:30","09:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","16:30","17:00","17:30","18:00","18:30","20:00","20:30","21:30"],
					["07:05","07:35","08:05","08:35","09:05","10:05","11:05","12:05","13:05","14:05","15:05","16:05","16:35","17:05","17:35","18:05","18:35","20:05","20:35","21:35"],
					["07:10","07:40","08:10","08:40","09:10","10:10","11:10","12:10","13:10","14:10","15:10","16:10","16:40","17:10","17:40","18:10","18:40","20:10","20:40","21:40"]];
var SCHEDULE20 = [	["07:15","08:15","09:15","11:15","13:15","15:15","16:15","17:15","19:15"],
					["07:20","08:20","09:20","11:20","13:20","15:20","16:20","17:20","19:20"],
					["07:25","08:25","09:25","11:25","13:25","15:25","16:25","17:25","19:25"],
					["07:30","08:30","09:30","11:30","13:30","15:30","16:30","17:30","19:30"],
					["07:35","08:35","09:35","11:35","13:35","15:35","16:35","17:35","19:35"]];
