new version, much refactored