Largely working.

* Needs more testing
* Some tidying