refactored for smaller methods and DRYness