this needs massive refactoring