working, needs testing, and cleanup