complete rewrite with TDD