major update and rewrite