refactored, needs testing