some refactoring...still in progress, use at your own risk