Pretty sure this works. Will need some testing and refactoring.