major refactoring; untested