rewritten to remove bugs