refactored, add tests