almost all tests written. Some test refactoring is required, though.