refactored, need to add some unit tests