a LOT of refactoring needed here...