finished, needs refactoring