implement almost all