This needs to be broken up into several small functions.