lots of refactoring
far too many changes for one commit, but the tests pass ...