more polished, but still need to refactor