address #3
complete rewrite, fix #1, fix #2, fix #4, address #3