refactor and add some features