// turn on logging statements in console from the code
function log(s) {
    debug = false;
    if (debug)
	console.log(s);
}

function recalc(v) {
    log ("...entering recalc");
    var calcables = document.getElementsByClassName("calcable");
    calcables.each(function(c) {
	    // the weekly mileage is just "contribution" * volume
	    if (c.up(2).id == "workouts" || c.up(3).id == "workouts" || c.up(1).hasClassName("workout_week")) {
		c.innerHTML = (parseFloat(c.readAttribute("contrib")) * v).toFixed(1);
	    // but weekdays is that * that workout's contribution
	    } else {
		var spanstr = ladders[qs["type"]][qs["level"]][c.up(2).previousSiblings().length - 1][7];
		spanstr.match(/.*contrib=\'([0-9\.]+)/);
		c.innerHTML = (parseFloat(c.readAttribute("contrib"))
			       * v
			       * parseFloat(RegExp.$1)
			       ).toFixed(1);
	    }
    });
}

// parse out any arguments from the querystring and return
function parseQueryString (str) {
    log ("...entering parseQueryString");
    str = str ? str : location.search;
    var query = str.charAt(0) == '?' ? str.substring(1) : str;
    var args = new Object();
    if (query) {
	var fields = query.split('&');
	for (var f = 0; f < fields.length; f++) {
	    var field = fields[f].split('=');
	    args[unescape(field[0].replace(/\+/g, ' '))] = 
		unescape(field[1].replace(/\+/g, ' '));
	}
    }
    return args;
}

// build the workout schedule for some race of some type at some level
function getWorkoutLadder(race, type, level) {
    log ("...entering getWorkoutLadder");
    var workoutWeek;
    document.title = "ChuckIt " + race + " workout schedule, " + level;
    var workout = "";
    var thisWeek = getFirstDayOfThisWeek();

    workout += "<table border='1'><th>Week starting</th><th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th>Saturday</th><th>Sunday</th>" +
	(level.match(/dor.*/) ? "<th>Goal mileage</th>" : "") +
	"</tr>";
    for (var week=0; week < ladders[type][level].length; week++) {
	workoutWeek = new Date(races[race].when.getYear(), 
			       races[race].when.getMonth(), 
			       races[race].when.getDate() - (ladders[type][level].length - week) * 7);
	workout += "<tr class='workout_week'>";
	var rowStyle = "";
	if (typeof(thisWeek) != "undefined" && 
	    workoutWeek.getMonth() == thisWeek.getMonth() &&
	    workoutWeek.getDate() == thisWeek.getDate()) {
	    rowStyle = "current";
	}
	workout += "<td class='dow " + rowStyle + "'>" + 
	    (workoutWeek.getMonth() + 1) +
	    "/" + 
	    (workoutWeek.getDate()) +
	    "</td>";
	ladders[type][level][week].each(function(day) {
	    workout += "<td class='" + rowStyle + "'>" + day + "</td>";
	});
	workout += "</tr>";
    }
    workout += "</table>";
    return workout;
}

// return true if the indicated race has a race of the specified distance
function raceHas(race, distance) {
    return (typeof(races[race].distances[distance]) != "undefined" &&
	races[race].distances[distance] == true);
}

// return an href if some url has been provided, empty string otherwise
function link(url, text, target) {
    //    return text.link(url);
    return (typeof(target) == "undefined" ? text.link(url) :
	    "<a href='" + url + "' target='" + target + "'>" + text + "</a>");
}

// return the current week workout for all future races
function getAllRaces(pageUrl, level, raceType) {
    log("...entering getAllRaces");
    var today = new Date();
    var weekStart = getFirstDayOfThisWeek();
    var content = "<h1>" + link('http://www.runchuckit.com/', "<img src='http://www.runchuckit.com/chuckit.gif'>", '_top') + " " + raceType + " " + level + " schedules " + 
	(typeof(weekStart) == "undefined" ? "" : "week starting " + (weekStart.getMonth() +1) + "/" + weekStart.getDate() ) + "</h1>";
    content += "<table border='1' cellspacing='0'><tr><th>Race</th><th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th>Saturday</th><th>Sunday</th></tr>";
    for (var race in races) {
	// omit past races and races that don't have this racetype
	if (today > races[race].when || ! raceHas(race, raceType)){
	    continue;
	}

	var weekIndex = ladders[raceType][level].length - Math.floor(((races[race].when.valueOf() - today.valueOf()))/1000/60/60/24/7) - 1;

	content += "<tr><td>" + link(pageUrl + "?type=" + raceType + "&race=" + race, races[race].name) + "</td>";
	if (weekIndex < 0) {
	    content += "<td colspan='7'>This schedule doesn't start yet</td>";
	} else {
	    ladders[raceType][level][weekIndex].each(function(day) {
		    content += "<td>" + day + "</td>";
		});
	}
	content += "</tr>";
    }
    content += "</table>";

    content += "Switch to " +
	"[" + link(pageUrl + '?race=all' + "&level=beginner&type=" + raceType, "Beginner", "_top") + "]" +
	"[" + link(pageUrl + '?race=all' +  "&level=intermediate&type=" + raceType, "Intermediate", "_top") + "]"+
	"[" + link(pageUrl + '?race=all' +  "&level=advanced&type=" + raceType, "Advanced", "_top") + "]";
    return content;
}

// return the date of "sunday this week" for row highlight
function getFirstDayOfThisWeek() {
    var firstDayThisWeek = new Date();

    if (firstDayThisWeek.getDate() > 7) {
	firstDayThisWeek.setDate(firstDayThisWeek.getDate() - firstDayThisWeek.getDay());
    } else {
	return;
    }

    return firstDayThisWeek;
}

function getRaceList(qs, pageUrl) {
    log ("...entering getRaceList");
    var now = new Date();
    var lastMonth = new Date();
    lastMonth.setMonth(lastMonth.getMonth() - 1);
    var raceList = "Pick a race below or view " + link(pageUrl + "?race=all&type=full", "full") + 
	" or " + link(pageUrl + "?race=all&type=half", "half") + " schedules for all races.";
    var fullByYear = $H();
    var halfByYear = $H();
    for (var race in races) {
	if (qs["filter"] == "all") {
	    // show this race
	} else if (qs["filter"] == "future" && lastMonth > races[race].when) {
	    continue;
	} else if (qs["filter"] == "past" && now < races[race].when) {
	    continue;
	}
        
	// build list of full marathons
	if (raceHas(race, 'full')) {
	    if (typeof(fullByYear[races[race].when.getFullYear()]) == "undefined") {
		fullByYear[races[race].when.getFullYear()] = new Array();
	    }
	    fullByYear[races[race].when.getFullYear()].push(race);
	}

	// build list of half marathons
	if (raceHas(race, 'half')) {
	    if (typeof(halfByYear[races[race].when.getFullYear()]) == "undefined") {
		halfByYear[races[race].when.getFullYear()] = new Array();
	    }
	    halfByYear[races[race].when.getFullYear()].push(race);
	}
    }
    raceList += "<table><tr><td>";
    // build a bulleted list of full marathons by year
    fullByYear.each(function(pair) {
	var year = pair.key;
	var yearRaces = pair.value;
	raceList += "<ul type='disc'><b>" + year + " Marathons:</b>";
	yearRaces.each(function(raceToken) {
	    var race = races[raceToken];
	    var raceUrl = pageUrl + "?type=full&race=" + raceToken;
	    raceList += "<li>" + link(raceUrl, race.name, "_top") + " | " +
		(race.when.getMonth() + 1) + "/" + race.when.getDate() + "/" + race.when.getFullYear() + " | " +
		link(race.url, "Race Info", "_blank") +
		"</li>";
	});
	raceList += "</ul>";
    });
    raceList += "</td><td>";
    // build a bulleted list of half marathons by year
    halfByYear.each(function(pair) {
	var year = pair.key;
	var yearRaces = pair.value;
	raceList += "<ul type='disc'><b>" + year + " Half-Marathons:</b>";
	yearRaces.each(function(raceToken) {
	    var race = races[raceToken];
	    var raceUrl = pageUrl + "?type=half&race=" + raceToken;
	    raceList += "<li>" + link(raceUrl, race.name, "_top") + " | " +
		(race.when.getMonth() + 1) + "/" + race.when.getDate() + "/" + race.when.getFullYear() + " | " +
		link(race.url, "Race Info", "_blank") +
		"</li>";
	});
	raceList += "</ul>";
    });
    raceList += "</td></tr></table>" +
	"</td></tr></table><hr>" +
	"Show only: " + link(pageUrl + "?filter=past", "past", '_top') + ", " +
	link(pageUrl + "?filter=future", "future", '_top') + ", " +
	link(pageUrl + "?filter=all", "all", '_top') + " races.";
    
    return raceList;
}

function initialize(element) {
    this.location.href.match(/(.*)(\?.*)/);
    var pageUrl = RegExp.$1;
    if (this.location.href.match(/workouts.htm/)) {
	return;
    }

    qs = parseQueryString();
    if (typeof(qs["filter"]) == "undefined") {
	qs["filter"] = "future";
    }

    // default peak week (for dor ladder)
    if (typeof(qs["volume"]) == "undefined") {
        // default to a 60 mile peak week
	qs["volume"] = 60;
    }

    // set defaults: no race, full, beginner
    var race = qs["race"] || "";
    var type = qs["type"] || "full";
    var level = qs["level"] || "beginner";

    var content = $(element);
    var body = "";
    var footer = "<hr><div><i>Go to " + link(pageUrl, "another race", "_top") + "</i></div>";

    if (race == "") {
	log("no race requested - showing all available races");
	body = getRaceList(qs, pageUrl);
	footer = "";
    } else if (race == "all") {
	// all races specifically requested? show all available races
	body += getAllRaces(pageUrl, level, type);
    } else if (typeof(races[race]) == "undefined") {
	// unknown race requested? - ERROR
	body = "Sorry, I don't know how to train for any races for " + race;
    } else if (! raceHas(race, type)) {
	// race type requested that we don't know about (e.g. a full at Nookachamps?) - ERROR
	body = "Sorry, I don't know how to train for a " + type + " at " + races[race].name + ".<br>";
    } else {
	// show the requested ladder
	body = "<h1><a target='_top' href='http://www.runchuckit.com/'><img src='http://www.runchuckit.com/chuckit.gif'></a><a target='_top' href='" + races[race].url + "'>" + races[race].name + "</a>" + " " + ladders[type].title + " - " + level + "</h1>";
  
	// add link to full, if there is one
	if (type != 'full' && raceHas(race, "full")) {
	    body += "Go to <a target='_top' href='" + pageUrl + '?race=' + race + '&type=full' + '&level=' + level + "'>full marathon</a> training program";
	// add link to half, if there is one
	} else if (type != 'half' && raceHas(race, "half")) {
	    body += "Go to <a target='_top' href='" + pageUrl + '?race=' + race + '&type=half' + '&level=' + level + "'>half marathon</a> training program";
	}
  
	if (level.match(/dor_a.*/)) {
	    body += "Enter peak weekly goal mileage: <input id='goal' size='5' onchange='recalc(this.value)' value='" + (typeof(qs["volume"]) == "undefined" ? 60 : qs["volume"]) + "' />" +
		"<input type='submit' value='update'>";
	}

	body += getWorkoutLadder(race, type, level);
  
	body += "Switch to " +
	    "[" + link(pageUrl + '?race=' + race + '&type=' + type + "&level=beginner", "Beginner", "_top") + "]"+
	    "[" + link(pageUrl + '?race=' + race + '&type=' + type + "&level=intermediate", "Intermediate", "_top") + "]"+
	    "[" + link(pageUrl + '?race=' + race + '&type=' + type + "&level=advanced", "Advanced", "_top") + "]";
    }
    content.innerHTML = body + footer;

    try {
	recalc(typeof(qs["volume"]) == "undefined" ? 60 : qs["volume"]);
    } catch (e) {
	// ignore if we couldn't set - probably isn't on this page;
    }
}

