full implementation