needs testing and refactoring.