<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO</title>
<script>
"use strict";

function fetch(method,url,data/*?*/,creds/*?*/,cb){
	if(!creds){
		cb=data;
		data=undefined;
		creds=undefined;
	} else if(!cb){
		cb=creds;
		creds=undefined;
	}
	if(!cb)throw new Error("No callback passed to fetch");
	var xhr=new XMLHttpRequest();
	xhr.onreadystatechange=function(ev){
		if(xhr.readyState<4)return;
		cb(xhr.status,xhr.responseText);
	};
	if(creds){
		xhr.open(method,url,true,creds[0],creds[1]);
	} else {
		xhr.open(method,url);
	}
	xhr.send(data);
}

function datesplit(date){
	return {
		year:date.getFullYear(),
		month:date.getMonth(),
		day:date.getDate(),
	    hour:date.getHours(),
	    min:date.getMinutes(),
	    sec:date.getSeconds()
	};
}

function pad(s,n,c){
	if(c==null)c=" ";
	else c=c[0];
	s=s+"";
	while(s.length<n)s=c+s;
	return s;
}

function beginOfDay(date){
	var d=new Date(date.getTime());
	d.setHours(0);
	d.setMinutes(0);
	d.setSeconds(0);
	d.setMilliseconds(0);
	return d;
}

function fancytime(timeS){
	return pad(timeS.hour,2,"0")+":"+pad(timeS.min,2,"0")+(timeS.sec==0?"":":"+pad(timeS.sec,2,"0"));
}

var weekdays=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];

function fancydate(date){
	var now=new Date();
	var nowS=datesplit(new Date());
	var dateS=datesplit(date);
	var diffdays=Math.round((beginOfDay(date).getTime()-beginOfDay(now).getTime())/1000/3600/24);
	if(date.getTime()<now.getTime()){
		if(diffdays==0)return "Earlier this day";
		return -diffdays+" day"+(diffdays==-1?"":"s")+" ago";
	}
	if(dateS.year==nowS.year&&dateS.month==nowS.month&&dateS.day==nowS.day){
		return "Today, "+fancytime(dateS);
	}
	var diffweeks=~~(diffdays/7);
	if(diffweeks>0){
		return weekdays[(date.getDay()+6)%7]+" in "+diffweeks+" week"+(diffweeks==1?"":"s");
	}
	if(diffdays==1){
		return "Tomorrow, "+fancytime(dateS);
	}
	return weekdays[(date.getDay()+6)%7]+", "+fancytime(dateS);
}

function tablerowfor(task){
	var div=document.createElement("div");
	div.classList.add("task");

	var e=document.createElement("span");
	e.classList.add("tasksubject");
	e.appendChild(document.createTextNode(task.subject));
	div.appendChild(e);

	var float=document.createElement("div");
	float.classList.add("taskfloat");

		e=document.createElement("span");
		e.classList.add("taskdate");
		e.appendChild(document.createTextNode((task.repweeks!=0?"(rep) ":"")+fancydate(task.date)));
		e.setAttribute("title",task.date.toString());
		e.appendChild(document.createElement("br"));
		var e2=document.createElement("span");
		e2.classList.add("subdate");
		e2.appendChild(document.createTextNode(task.date.toString()));
		e.appendChild(e2);
		float.appendChild(e);

		e=document.createElement("span");
		e.classList.add("taskdelete");
		e.appendChild(document.createTextNode("X"));
		e.addEventListener("click",function(ev){
			if(!confirm("Really delete task \""+task.subject+"\"?"))return
			fetch("DELETE","/todo/task",task.id,function(status,body){
				if(status==200)getlist();
				else alert("Delete failed: "+body);
			});
		});
		float.appendChild(e);

	div.appendChild(float);

	return div;
}

function refreshlist(list){
	var listelem=document.getElementById("todolist");
	listelem.innerHTML="";
	var rows=[];
	var i,task;
	var now=new Date();
	for(i=0;i<list.length;i++){
		task=list[i];
		if(task.repweeks!=0){
			while(task.date<now){
				task.date=new Date(task.date.getTime()+task.repweeks*7*24*3600*1000);
			}
		}
		rows.push([task.date,tablerowfor(task)]);
	}
	if(rows.length==0){
		var div=document.createElement("div");
		div.classList.add("notasks");
		div.appendChild(document.createTextNode("No tasks :D"));
		listelem.appendChild(div);
		return;
	}
	rows.sort(function(a,b){return a[0]-b[0];}); //ascending sort on the dates
	for(i=0;i<rows.length;i++){
		listelem.appendChild(rows[i][1]);
	}
}

function getlist(){
	fetch("GET","/todo/list",function(status,json){
		var list;
		try {
			list=JSON.parse(json);
		} catch(e){
			alert("An error occurred!");
			return;
		}
		var i;
		for(i=0;i<list.length;i++)list[i].date=new Date(list[i].date);
		refreshlist(list);
	});
}

function doOpenAddTask(ev){
	document.getElementById("addtaskform").classList.remove("invisible");
	ev.target.parentNode.removeChild(ev.target);
}

function doAddTask(ev){
	var subject=document.getElementById("addtasksubject").value;
	var repweeks=+document.getElementById("addtaskrepweeks").value;
	var date=document.getElementById("addtaskdate").value;
	if(typeof date=="string")date=new Date(date);
	if(isNaN(repweeks)){
		alert("Invalid repweeks!");
		return;
	}
	fetch("POST","/todo/task",JSON.stringify({
		subject:subject,
		repweeks:repweeks,
		date:date
	}),function(status,body){
		if(status==200){
			location.href=location.href;
			return;
		}
		alert("Error while adding: "+body);
	});
}

function logoutReload(){
	fetch("GET","/todo/authfail",undefined,["baduser","badpass"],function(status,body){
		location.href=location.href;
	});
}

window.addEventListener("load",getlist);
</script>
<style>
body{
	font-family:Georgia,Times,serif;
	font-size:14px;
}
.task{
	border:1px #ddd solid;
	border-bottom-width:0px;
	padding:10px;
	background-color:#f8f8f8;
	width:500px;
}
.task:last-child{
	border-bottom-width:1px;
}
.tasksubject{
	font-size:18px;
	font-weight:bold;
	margin-left:10px;
}
.taskfloat{
	float:right;
	text-align:right;
}
.taskdate{
	font-size:12px;
	font-style:italic;
	display:inline-block;
}
.subdate{
	color:#ccc;
	font-size:8px;
}
.taskdelete{
	margin-left:60px;
	font-size:10px;
	font-family:sans-serif;
	color:red;
	cursor:pointer;
	vertical-align:top;
}
#addtaskform{
	border:1px #ddd solid;
	display:inline-block;
	padding:5px;
}
#addtaskform.invisible{
	display:none;
}
#logoutwrapper{
	float:right;
}
</style>
</head>
<body>
<div id="logoutwrapper">
	<input type="button" onclick="logoutReload();" value="Logout">
</div>
<h1>TODO</h1>
<div id="todolist"></div>
<br><br>
<input type="button" onclick="doOpenAddTask(event)" value="Add task">
<div id="addtaskform" class="addtaskform invisible">
	Subject: <input type="text" id="addtasksubject" placeholder="Subject"> <br>
	Repweeks: <input type="number" id="addtaskrepweeks" placeholder="Repweeks" value="0" min="0"> (0 = no repeat) <br>
	Date: <input type="datetime" id="addtaskdate" placeholder="YYYY-MM-DD HH:MM:SS" size="25"> <br>
	<input type="button" onclick="doAddTask(event)" value="Add">
</div>
</body>
</html>