refactored. almost working, not tested