major refactoring, but the code is easier now