var SETTINGS = {
	//email: "christian_hammer@hotmail.com"
	email: "info@nordkystenskoereskole.dk"
	,emailBCC: "christian_hammer@hotmail.com"
}
var regexp_newLine = new RegExp( "\\n\\r", "g" );
var regexp_newLine2 = new RegExp( "[\\n\\r]", "g" );

function translateNewlines(str) {
	return str.replace(regexp_newLine,"<br/>").replace(regexp_newLine2,"<br/>");
}
function encode(str) {
	var out = '';
	var c;
	var h = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
	for (var i=0;i<str.length;++i) 
		switch (c=str.charAt(i)) {
		case '\b': out += '\\b'; break;
		case '\t': out += '\\t'; break;
		case '\n': out += '\\n'; break;
		case '\f': out += '\\f'; break;
		case '\r': out += '\\r'; break;
		case '\\': out += '\\\\'; break;
		case '"': out += '\\"'; break;
		case '\'': out += '\\\''; break;
		default:
			var cc = str.charCodeAt(i);
			if (0<=cc && cc<=15) out += "\\0x0"+h[cc];
			else if (cc<=31) out += "\\0x1"+h[cc-31];
			else out += c;
			break;
		}
	return out;
}
function stripFunctions(obj) {
	for (var p in obj) {
		if (typeof(obj[p])=="function") try {
			obj[p] = undefined;
			delete obj[p];
		} catch (x0) {
		}
	}
	return obj;
}
function copyValues(source,target) {
	if (!source) return target;
	if (target) for (var p in source) 
		if (typeof(source[p])!="function") target[p] = source[p];
	return target;
}
function js_toJSON(obj,expandFunctions) {
	if (obj===null) return 'null';
	if (obj===undefined) return 'undefined';

	if (typeof(obj)=='boolean') return obj.toString();
	if (typeof(obj)=='function' && expandFunctions) return obj.toString();
	if (typeof(obj)=='object' && obj.getUTCFullYear) {
		return "new Date("+
			obj.getFullYear()+","+
			obj.getMonth()+","+
			obj.getDate()+","+
			obj.getHours()+","+
			obj.getMinutes()+","+
			obj.getSeconds()+","+
			obj.getMilliseconds()+")";
	}

	//if (typeof(obj)=='object' && obj.toJSON) return obj.toJSON();
	switch (typeof(obj)) {
		case 'object':
			var comma = false;
			var arr = obj.splice && obj.join;
			var out = arr?'[':'{';
			if (arr) for (var i=0;i<obj.length;++i) {
				if (comma) out += ','; comma = true;
				out += js_toJSON(obj[i]);
			} else for (var p in obj) {
				if (obj[p]==undefined) continue;
				if (typeof(obj[p])=="function" && !expandFunctions) continue;
				
				if (comma) out += ','; comma = true;
				out += p+':'+js_toJSON(obj[p]);
			}
			return out + (arr?']':'}');
			break;
		case 'string': return '"'+encode(obj)+'"'; break;
		case 'number': return ""+(0+obj); break;
	}
	return "undefined";
}
function js_toArrayString(array) {
	var out = "", comma = false;
	for (var i=0;i<array.length;++i) {
		if (comma) out += ','; comma = true;
		out += js_toJSON(array[i]);
	}
	return out;
}
function js_QUERY(conn,query) {
	var sqlQuery = conn.Execute(query);
	if (sqlQuery.ActiveConnection.Errors.Count>0) sqlQuery = null;
	return sqlQuery;
}
function js_INSERT(object,type,access,name) {
	var result = [];
	var isArray = (object.splice!=undefined);
	if (!isArray) object = [object];

	for (var i=0;i<object.length;++i) {
		var o = object[i];
		var rowID = o.rowID;
		if (o.action) o.action=undefined;
		for (var p in o) if (p.indexOf("row")==0) o[p]=undefined;
		result.push({object:o, sql:"insert into ks_data values (0,'"+type+"',"+access+",now(),'"+js_toJSON(o)+"','"+name+"')"});
	}
	return isArray?result:result[0];
}
function js_DELETE(object) {
	var result = [];
	var isArray = (object.splice!=undefined);
	if (!isArray) object = [object];
	
	for (var i=0;i<object.length;++i) {
		var o = object[i];
		if (o.rowID!=undefined)	result.push({object:o, sql:"delete from ks_data where id="+o.rowID});
	}
	if (result.length==0) return null;
	return isArray?result:result[0];
}
function js_SELECT(type,access,name,ids) {
	var extra = " ";
	if (ids) extra += "and id in ("+js_toArrayString(ids)+") ";
	if (name) extra += "and name='"+name+"' ";
	return "select * from ks_data where type='"+type+"' and access>="+access+extra;//+" order by id ASC";
}
function js_UPDATE(object) {
	var result = [];
	var isArray = (object.splice!=undefined);
	if (!isArray) object = [object];
	
	for (var i=0;i<object.length;++i) {
		var o = object[i];
		var rowID = o.rowID;
		if (rowID!=undefined) {
			if (o.action) o.action=undefined;
			for (var p in o) if (p.indexOf("row")==0) o[p]=undefined;
			result.push({object:o, sql:"update ks_data set data='"+js_toJSON(o)+"' where id="+rowID});
		}
	}
	if (result.length==0) return null;
	return isArray?result:result[0];
}

// -- KS Admin methods
function sortByNumericField(values,fieldId) {
	return values.sort(function(a,b) { return a[fieldId]-b[fieldId]; });
}
function js_getClasses(conn,ids) {
	var classes=[];
	var row = js_QUERY(conn,js_SELECT("class",50,null,ids));
	while (!row.EOF) {
		var cls = getRowObject(row);
		cls.classType = row.name;
		classes.push(cls);	
		row.moveNext();
	}
	return classes; //sortByNumericField(classes,"start");
}
function js_getCalendar(conn,id) {
	var calendar = null;
	var row = null;

	row = js_QUERY(conn,js_SELECT("calendar",50,id));	
	if (!row.EOF) calendar = getRowObject(row);
	if (!calendar) return null;
	
	var groups=[];
	row = js_QUERY(conn,js_SELECT("group",50,null,calendar.groups));
	while (!row.EOF) {
		var cls = getRowObject(row);
		groups.push(cls);
		cls.classes = js_getClasses(conn,cls.classes);
		row.moveNext();
	}
	calendar.groups = groups;
	return calendar;
}
function js_getPrices(conn,id) {
	var row = js_QUERY(conn,js_SELECT("price",1000,id));	
	if (!row.EOF) return getRowObject(row);
	return null;
}

function js_extendObject(obj) {	
	obj.get=function(conn) { 
		var row = js_QUERY(conn,js_SELECT());
		if (row.EOF) return null;
		return copyValues(getRowObject(row),this);
	}
	obj.put=function(conn) {
		var sql = js_INSERT(this,this.type,100,this.name);
		if (!sql) return null;
		js_QUERY(conn,sql.sql);
		return this;
	}
	obj.update=function(conn) {
		var sql = js_UPDATE(this);
		if (!sql) return null;
		js_QUERY(conn,sql.sql);
		return this;
	}
	obj.remove=function(conn) {
		var sql = js_DELETE(this);
		if (!sql) return null;
		js_QUERY(conn,sql.sql);
		return this;
	}
	switch (obj.type) {
		case 'student':
			if (obj.rowID==undefined) { // Creating new student - check if he/she already exist
				obj.put=function(conn) { 
					this.convertClasses(conn);
					var sql = js_INSERT(this,this.type,100,this.name);
					if (!sql) return null;
					js_QUERY(conn,sql.sql);					
					return this; 
				}
			} else {
				obj.put=function(conn) { 
					this.convertClasses(conn);
					return this.update(conn); 
				}
			}
			obj.convertClasses=function(conn) {
				var students = js_getByType(conn,"student");
				var found = -1;
				for (var i=0;found<0 && i<students.length;++i) 
					if (students[i].email==this.email) found = i;
				if (found>=0) copyValues(students[found],this);			
				
				if (!this.classes) this.classes = [];
				if (this.mc) {
					for (var i=0;i<this.classes.length;++i) 
						if (this.classes[i].rowID==this.mc.rowID) { this.mc = undefined; break; }
					if (this.mc) this.classes.push({ rowID: this.mc.rowID, type: 'mc', confirmed: false });
				}
				if (this.bil) {
					for (var i=0;i<this.classes.length;++i) 
						if (this.classes[i].rowID==this.bil.rowID) { this.bil = undefined; break; }
					if (this.bil) this.classes.push({ rowID: this.bil.rowID, type: 'bil', confirmed: false });
				}
				if (this.mc || this.bil) mail_signUpForClass(conn,this);
				this.mc = undefined;
				this.bil = undefined;					
			}
			obj.update=function(conn) {
				if (this.action && this.action.type=="confirm") 
					for (var i=0;this.classes.length;++i) 
						if (this.classes[i].rowID==this.action.classID) {
							this.classes[i].confirmed=!!this.action.value;
							this.action = undefined;
							break;
						}
					
				var sql = js_UPDATE(this);
				if (!sql) return null;
				js_QUERY(conn,sql.sql);	
				return this;				
			}
			break;
		case 'message':
			//var row = js_QUERY(conn,"select * from ks_data where type='student' and name='"+obj.name+"'");
			//obj.name = obj.receiver;
			obj.put=function(conn) {
				var sql = js_INSERT(this,this.type,100,this.name);
				if (!sql) return null;
				js_QUERY(conn,sql.sql);								
				if (!this.rowID) {
					var r = js_QUERY(conn,"SELECT LAST_INSERT_ID()");
					if (!r.EOF) this.rowID = r.fields(0);
				}
				mail_forward(this);
				return this;
			}
			break;
		case 'calendar':
			obj.get=function(conn) {
				//var obj = js_getCalendar(conn,"calendar"+this.date.getFullYear());
				//return copyValues(obj,this); 
				this.calendar = js_getCalendar(conn,"calendar2009"/*+this.date.getFullYear()*/);
				return this;
			}
			break;
		case 'config':
			obj.get=function(conn) {
				this.calendar = js_getCalendar(conn,"calendar2009"/*+this.date.getFullYear()*/);
				this.prices = js_getPrices(conn,"prices2009a");
				return this; 
			}
			break;
	}
	if (!obj.type) {
		var row = js_QUERY(conn,"select * from id="+obj.rowID);
		if (!row.EOF) obj = copyValues(getRowObject(row),obj);
	}	
	return obj;
}
function js_getByType(conn,type,filter) {
	var objects = [];

	var row = js_QUERY(conn,"select * from ks_data where type='"+type+"' order by id ASC");
	while (!row.EOF) {
		try {
			var obj = getRowObject(row);
			if (!filter || filter(obj)) objects.push(obj);
		} catch (x) {
			//objects.push(x);
		}
		row.moveNext();		
	}
	return objects;
}
var getJSONObject=function(str) { return eval(translateNewlines("_="+str)); }
var getRowObject=function(row) {
	var obj = getJSONObject(row.fields("data"));
	obj.rowID = 0+row.fields("id");
	obj.rowCreated = ""+row.fields("created") //TODO Convert me!
	obj.row = {
		type: ""+row.fields("type"),
		access: 0+row.fields("access"),
		name: ""+row.fields("name")
	}
	return stripFunctions(obj);
}

var apply=function(objects,fnc) {
	for (var i=0;i<objects.length;++i) fnc(objects[i]);
}
var filter=function(objects,filter) {
	var output = [];
	for (var i=0;i<objects.length;++i)
		if (filter(objects[i])) output.push(objects[i]); 
	return output;
}

var deleteObject=function(object,element) {
	if (object==undefined) return;
	if (element && !element.addClassName) document.extendElement(element);
	AjaxServer.remove(
		object,
		function(result) { element.parentNode.removeChild(element); },
		function(error) { alert(error.message);	},
		function() { element.addClassName("loading"); },
		function() { element.removeClassName("loading"); }
	);
}
var updateObject=function(object,element) {
	if (object==undefined) return;
	if (element && !element.addClassName) document.extendElement(element);
	AjaxServer.update(
		object,
		function(result) { alert("OK"); },
		function(error) { alert(error.message);	},
		function() { element.addClassName("loading"); },
		function() { element.removeClassName("loading"); }
	);
}
function evaluateText(text,context) {
	var out = "";	
	var start=0,end=0;
	with (context) {
		var today = new Date();
		while ((start=text.indexOf("##",end))>=0) {
			out += text.substring(end,start);
			end = text.indexOf("##",start+2);
			if (end<=0) break;
			try {
				out += eval(text.substring(start+2,end));
			} catch (x) {
				out += "!!FEJL "+x+"!!";
			}
			end += 2;
		}
	}
	if (end==0) return text;
	return out + text.substring(end);
}
function createMail(content) {
	var head = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n";
	head += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
	head += "<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='da' lang='da'>";
	head += "<head>";
	head += "<meta http-equiv='content-type' content='text/html; charset=UTF-8' />";
	head += "<meta http-equiv='content-language' content='da' />";
	head += "<style type='text/css'>";
	head += ".right { text-align: right; }\n";
	head += ".mail {\n";
	head += "   font-family: Arial, Helvetica, Georgia, Sans-Serif; font-size: 12px;\n";
	head += "   vertical-align: top; color: #000000; padding: 10px;\n"
	head += "}\n";
	head += ".mail .info {}\n";
	head += ".mail .info .property { width: 60px; }\n";
	head += ".mail .info .value {}\n";
	head += "</style></head>";

	return head+"<body class='mail'>"+translateNewlines(content)+"</body></html>";
}
function mail_signUpForClass(conn,student) {
	var ids = [];
	if (student.bil) ids.push(student.bil.rowID);
	if (student.mc) ids.push(student.mc.rowID);
	
	var classes = js_getClasses(conn,ids);	
	var clss = "";

	var prices = js_getPrices(conn,"prices2009a");

	var info = null;
	var mailBody = null;
	var developmentMessage = "";
/*
		if (clazz.teacher==undefined) {
			clazz.teacher = 0;
			if (clazz.row.name!="mc") clazz.teacher = 1;
		}
		if (clazz.title==undefiend) {
			clazz.title = "MC";
			if (clazz.row.name!="mc") clazz.title = "bil";
		}
*/	
	if (student.bil && student.mc) {
		var clsBIL = classes[0];
		var clsMC = classes[1];
		if (clsBIL.classType!="bil") {
			clsBIL = classes[1];
			clsMC = classes[0];
		}
		if (!clsBIL.title) clsBIL.title = "Bil";
		if (!clsMC.title) clsMC.title = "MC";
		
		clss += clsBIL.title+" ("+clsBIL.start.format()+") og "+clsMC.title+" ("+clsMC.start.format()+")"; 

		info = {
			student: student,
			teacher: teachers[0],
			bil:{
				clazz: clsBIL,
				days: clsBIL.start.format("DDD! kl. hh:mm"),
				comboprice: 8100,
				price: prices.bil
			},
			mc:{
				clazz: clsMC,
				days: "Tirsdag og Torsdag kl. "+clsMC.start.format("hh:mm"),
				comboprice: 8100,
				price: prices.mc
			}
		};
		mailBody = mailSignUpCombo;
	} else if (student.bil) {
		var clsBIL = classes[0];
		if (!clsBIL.title) clsBIL.title = "Bil";
		clss += clsBIL.title+" ("+clsBIL.start.format()+")"
		info = {
			student: student,
			teacher: teachers[1],
			clazz: clsBIL,
			price: prices.bil,
			days: clsBIL.start.format("DDD! kl. hh:mm")
		};
		mailBody = mailSignUp;
	} else if (student.mc) {
		var clsMC = classes[0];
		if (!clsMC.title)clsMC.title = "MC";
		clss += clsMC.title+" ("+clsMC.start.format()+")"; 
		info = {
			student: student,
			teacher: teachers[0],
			clazz: clsMC,
			price: prices.mc,
			days: clsMC.start.format("Tirsdag og Torsdag kl. hh:mm")
		};
		mailBody = mailSignUp;
	}
	
	if (mailBody && info) try {
		var contentSignUp = evaluateText(mailBody,info);
		var objMailStudent = Server.CreateObject("CDONTS.NewMail");
		objMailStudent.BodyFormat = 0;
		objMailStudent.Host = "mailout.one.com";
		objMailStudent.To = student.email;
		objMailStudent.From = SETTINGS.email;
		objMailStudent.Cc = SETTINGS.email;
		if (SETTINGS.emailBCC) objMailStudent.Bcc = SETTINGS.emailBCC;

		objMailStudent.Subject = "Tilmelding til "+clss
		objMailStudent.Body = createMail(contentSignUp);
		objMailStudent.Send();
	} catch (x) {
		developmentMessage = "<br/>Mail failure: "+x;
	}

	if (clss.length==0) clss="???";
	
	var content = student.name+" &oslash;nsker at tilmelde sig til "+clss+"<br/><table class='info' border='0'><thead>";
	content += "<tr><th class='property'></th><th class='value'></th></tr>";
	content += "</thead><tbody>";
	content += "<tr><td>Navn</td><td>"+student.name+"</td></tr>";
	content += "<tr><td>Adresse</td><td>"+student.address+"</td></tr>";
	content += "<tr><td>By</td><td>"+student.city+"</td></tr>";
	content += "<tr><td>Mobil</td><td>"+student.cell+"</td></tr>";
	content += "<tr><td>CPR</td><td>"+student.cpr+"</td></tr>";
	content += "<tr><td>Bem&aelig;rkning</td><td>"+translateNewlines(student.remark)+"</td></tr>";	
	content += "</tbody></table>";
		
	var objMail = Server.CreateObject("CDONTS.NewMail");
	objMail.BodyFormat = 0;
	objMail.Host = "mailout.one.com";
	objMail.To = SETTINGS.email;
	objMail.From = SETTINGS.email;
	if (SETTINGS.emailBCC) objMail.Bcc = SETTINGS.emailBCC;

	objMail.Subject = student.name+" er tilmeldt "+clss;
	objMail.Body = createMail(content+"<br/><hr><b>Udvikling</b><br/>"+developmentMessage+"<br/>data="+js_toJSON(student));
	objMail.Send();
}
function mail_forward(message) {
	if (!message.email || message.email.length<6) throw new "Ugyldig e-mail-adresse.";
	
	var objMail = Server.CreateObject("CDONTS.NewMail");
	
	objMail.BodyFormat = 0;
	objMail.Host = "mailout.one.com";
	objMail.To = SETTINGS.email;
	objMail.From = message.email;
	if (SETTINGS.emailBCC) objMail.Bcc = SETTINGS.emailBCC;
	
	objMail.Subject = "Ny henvendelse fra "+(message.name?message.name:"anonym");
	objMail.Body = createMail(message.remark);
	objMail.Send();
}
function mail_sendStandard(mail,user) {
	var objMail = Server.CreateObject("CDONTS.NewMail");
	
	objMail.Format = 0;
	objMail.Host = "mailout.one.com";

	objMail.To = user.email;
	objMail.From = mail.sender;
	objMail.Subject = mail.title;
	objMail.Body = mail.content;

	if (mail.attachFiles) {
		for (var i=0;i<mail.attachFiles.length;++i)
			objMail.AttachFile(mail.attachFiles[i]);
		//objMail.MailFormat = 0; -- set to MIME
	}
	if (mail.attachURLs) {
		for (var i=0;i<mail.attachURLs.length;++i)
			objMail.AttachURL(mail.attachURLs[i]);
		//objMail.MailFormat = 0; -- set to MIME
	}
	objMail.Send();
}
