updated with some bugs discovered.