refactor the code, add event channel