functional version, needs cleaning