refactored and final version