This is pretty complicated. Maybe it should be in it's own class?