I wrote this in a hurry. There are probably bugs.