refactor and some optimisation