refactored to use event emitter