not tested, nearly complete code