added tests, lots of refactoring