a lot of refactor