it's messy, needs refactoring