Completely refactored this code to be more extinsible