Lots of refactoring and tests added.