Working version.
Needs testing and exceptions.