refactored to be more single responsibility and added caching