quite a bit of refactoring here

I've removed some duplication and improved the code.