final product, needs refactoring