working version (needs more testing)