big refactor to be easier to extend