needs tests, has all the code though