Add tests and do major refactoring