remake and refactorize