needs some clean-up but practically done