Too much changes to describe. See the code.